Hacker Newsnew | past | comments | ask | show | jobs | submit | SoundAndBug's commentslogin

What does solve the problem?


My take on it would be the approach from SICP[0]: separate data (objects) from transformations (streams). On a personal note I would also like to add:

- keep data serializable

- cluster transformations accordingly (Keep things that belong to each other as close as possible to each other, in a literal meaning, same file/module/etc. A new coworker should have the feeling of entering a public library - she'll know where to look for.)

- it will probably never be the case that you have to invent a new data structure or algorithm

Developers understand such terms like 'function' in very different ways (see top comment in this thread). Some have a more abstract approach and understand it as 'pure', where others have a more instruction-bundeling approach and understand it as 'procedure'. Either is valid, but are completely orthogonal to each other when it comes to its usage. I understand Gary Bernhards approach to 'functional core, imperative shell'[1] as a mean to talk about this - instructions demand for composable building blocks, and those building blocks come either from:

- built-in functions (with an already universally understood API)

- or your own (clustered) utils (and demand an easily understandable API).

[0]: https://mitpress.mit.edu/sites/default/files/sicp/index.html

[1]: https://www.destroyallsoftware.com/screencasts/catalog/funct...


I don't see how this solves the problem. I can have pure functions for parsing the HTML of each site: they take the text and return a simple data structure with the information I need. Chances are, if you write one and then another, you'll find there's plenty of duplicated code. Should you try to decompose those parts into common (pure) functions or not?


I assume your API can be expressed as this function signature:

  parseDataFromHTMLResource :: Resource -> HTMLRaw -> Maybe Data
...and assuming we validate the HTML:

  validateHTML :: HTMLRaw -> Maybe HTML
I think your question relies on the separation of 'Resource', as a domain separation like right below will probably create a lot of duplication (since any resource is free to structure their HTML within the standard however they want):

  parseDataFromGoogleHTML :: HTML -> Maybe Data
  parseDataFromGithubHTML :: HTML -> Maybe Data
  parseDataFrom...
Perhaps you can reduce the duplication by converging to different fingerprinted resources. So a HTML resource, fingerprinted by style, will then guarantee your data:

  data HTMLFingerprinted =
      HTMLStyleGoogle
    | HTMLStyleGithub
    | ...
  
  htmlFingerprintedFromHTML :: HTML -> Maybe HTMLFingerprinted -- So the Maybe will be here
  parseDataFromHTMLFingerprinted :: HTMLFingerprinted -> Data  -- ...not here
(Note that this may be what the parent means. It helps solving "For me it's usually, "Oh crap that thing I changed I had to change here and here too, whoops its good now... Wait no I also had to change it here... and here... now that we're done with that we should be fine... DAMMIT!"" with "I just create this abstraction".)

I would say if you're able to implement the function 'htmlFingerprintedFromHTML', you deserve the abstraction and thus DRY the codebase on the fly. And this "no pain no gain" mantra is what I personally really like on a 'functional core'. Code stays only duplicated where absolutely needed until you find a solution for the abstraction.

...and I guess implementations of fingerprinting HTML may vary a lot.


Yeah, I have no idea. Code that avoids this problem is mostly DRY if you look after the fact, but going from the DRY principle to code does very often lead to the wrong abstractions (that won't solve the problem at all) and too little repetition (that will make your code break on the opposite way: you change one piece and unrelated stuff breaks).

DRY is a good learning tool, and it is an after the fact property of good code. But people shouldn't ever preach it.


This looks amazing.

Can you share which micro-controller are you using?


Thanks! I’ve tried a bunch of different arduino/compatible units. Early ones started with Duos. Some others used Sparks. It’s more a function of what bus voltages are needed for the LED controllers. If possible I prefer to not use line lever converters. Currently I used a customized protoboard but am planning on custom PCB in the future. Each one is generally an improvement on the last due to streamlining processes.


It's interesting to see what can be done with the Web APIs.

This is my venture into the Web Audio API (+ websockets): https://www.personalecho.com/jam

It's pretty basic, but I find it fun. I used Tone.js for it.


Tone.js is great! Also check out timbre.js if you haven't.


Is this it: https://github.com/mohayonao/timbre.js/ ? (It says it's not maintained anymore)

What does it offer that Tone.js does not?


Yikes, just realized it's no longer maintained.

Timbre lets you do more advanced stuff in a simpler way (less lines of code), although the last time I used Tone.js was a long time ago, so things might be different now.

Take a look at the Timbre.js examples!


Can you explain why do you want to get rid of reducers? What do you gain from it?

Good luck with the social network. Seems like a tough job.


With the spread (...foo) operator you can already merge json objects. However in order to use it you need to have access to the objects you make reference to.

This is how it would work: In the front end (like in react-redux) you have your state variable and then you normally make a request to the backend, which the backend returns this "JSON2" object, which you can merge automatically (with JSON2.merge method) to create the new state, without requiring reducers. The only thing is that the back-end would need to be aware of how the front-end state structure looks like (it doesn't need to keep track of the current state though).

// the front-end state

let state = { some: "things", nested: { something: { what: "what", } }, other: [2,3] }

// action is a string with JSON2 format that comes from a query to the back-end. Take the "..." literally

let action = "{ ..., nested: { something: { ..., more: "manymore" } }, other: [1, ...] }"

// create the new state

state = JSON2.merge(state, action)

// now state is:

state = { some: "things", nested: { something: { what: "what", more: "manymore" } }, other: [1,2,3] }


Developer here. I heard some of you try out this little app. If you have any feedback, I'd love to hear it.

Would you use it in the future, if it were more polished?


How much of a delay did you experience?

I was worried about it before I made this, but I haven't noticed any considerable lag. The server is in France. If you're not from Europe, this could be the reason for the delay.


I'm in Italy and the delay is acceptable


Thanks. Good to know.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: