Live data from Hacker News

Magical, Mystical JavaScript Transducers

jrsinclair.com

21–30 of 51 posts

Re: Magical, Mystical JavaScript Transducers

#21
post #3

Impressive amount of code and words. I think I'd think twice before approving this in a code review, though. Why is this not the obvious solution to the stated problem? function avgPopularity(slang) { let sum = 0; let count = 0; for (item of slang) { if (item.popularity > 0) { sum += item.popularity; count += 1; } } return sum / count; }

Yours is the obvious solution but the problem is a simple example to help people understand the more complex idea of transducers. It's for situations where the code inside the for loop is so complex that it would be nice to organize it with functional programming principals. The problem with functional programming is that the obvious approach is not efficient since it passes the array several times. So the goal is to…

FP works very well in short simple examples. If the for loop would be any more complex the FP solution would probable be incomprehensible. Optimizers however love small immutable and steteless functions so FP would likely be faster then the imperative version. For example by making it run parallel, caching, inlining, etc

Re: Magical, Mystical JavaScript Transducers

#22
post #3

Impressive amount of code and words. I think I'd think twice before approving this in a code review, though. Why is this not the obvious solution to the stated problem? function avgPopularity(slang) { let sum = 0; let count = 0; for (item of slang) { if (item.popularity > 0) { sum += item.popularity; count += 1; } } return sum / count; }

Your solution requires that slang be fully populated upfront, while the article shows a solution that can operate on a stream of data, an item at a time.

False. It can just as well be a lazy iterator that returns data one by one from a stream.

Re: Magical, Mystical JavaScript Transducers

#23
I am somewhat confused here, I primarily do C# so I am used to IEnumerable and Linq for doing this kind of stuff and you would just do .Where().Select().Average() without worrying about intermediate memory usage. In C# you do this stuff with millions of results from a database (although you would do in the db if you can, but might be a flat file too).

Linq with IEnumerable doesn't necessarily create intermediate list (js arrays) in memory unless it has to like say .OrderBy()

So I basically assumed js was the same since it has generators but its seems map and filter etc don't support them yet?:

https://dev.to/nestedsoftware/lazy-evaluation-in-javascript-...

So then you get a solution like this that looks to me very confusing vs a fluent style.

Please tell me I am missing something

Re: Magical, Mystical JavaScript Transducers

#24
post #3

Impressive amount of code and words. I think I'd think twice before approving this in a code review, though. Why is this not the obvious solution to the stated problem? function avgPopularity(slang) { let sum = 0; let count = 0; for (item of slang) { if (item.popularity > 0) { sum += item.popularity; count += 1; } } return sum / count; }

Yours is the obvious solution but the problem is a simple example to help people understand the more complex idea of transducers. It's for situations where the code inside the for loop is so complex that it would be nice to organize it with functional programming principals. The problem with functional programming is that the obvious approach is not efficient since it passes the array several times. So the goal is to…

The fact that it creates multiple intermediate arrays is a sign of the bad design in js ... and why (IMHO) if you want to do functional programming, sticking to a functional programming language can be a better option.

Re: Magical, Mystical JavaScript Transducers

#25
post #3

Impressive amount of code and words. I think I'd think twice before approving this in a code review, though. Why is this not the obvious solution to the stated problem? function avgPopularity(slang) { let sum = 0; let count = 0; for (item of slang) { if (item.popularity > 0) { sum += item.popularity; count += 1; } } return sum / count; }

The article obfuscates the point. Reducers/transducers are from the FP world. In FP avoiding mutable state is one the main point. dot = field => obj => obj[field] // unsafe Array.average = self -> reduce(add, self) / self.length // unsafe slang.filter(s -> s.popularity > 0) .map(dot('popularity')) .average() Bonus points: - no state - reusable pure functions - a tad shorter - maybe as readable as the `for over state`…

Downside: Still going over the array multiple times.

Re: Magical, Mystical JavaScript Transducers

#26

Every time I see this blog I'm extremely interested in the content, but the stylized presentation is so jarring and tough to read. I doubt this is an original qualm and I'm fully able to switch to reading mode in Firefox to mitigate this problem, but frankly it's off-putting.

I don't mind the font, but the pointlessly narrow column (which makes you have to horizontally scroll the code examples) is unfortunate.

Please, I have a wide screen, let me use it.

Re: Magical, Mystical JavaScript Transducers

#27
post #19

Earlier quoted context omitted.

For me it's the other way around. A for loop is a general purpose solution that changes continuously with the problem: whenever I need to gather some extra data, just add some hairs to the for loop. The time complexity is obvious, so is the space complexity (how much data is in memory at any given time), and it's easy to pause and debug. But if you have a bunch of FP combinators and recursion schemas, when the proble…

That seems to be such a basic task. Please take it not as me not believing it but could you provide some source about there not being a known O(N) solution for that problem, I'd like to know what the hurdles are and why there might be no solution at all or why finding one is so difficult. (I tried googling it but failed to find something useful)

Because of the whole immutability dogma of FP languages, you can't do this simply in a clean FP style:

    ++(histogram[sampleId]);
which is the heart of a simple histogram computation.

Re: Magical, Mystical JavaScript Transducers

#28

Earlier quoted context omitted.

Yours is the obvious solution but the problem is a simple example to help people understand the more complex idea of transducers. It's for situations where the code inside the for loop is so complex that it would be nice to organize it with functional programming principals. The problem with functional programming is that the obvious approach is not efficient since it passes the array several times. So the goal is to…

For me it's the other way around. A for loop is a general purpose solution that changes continuously with the problem: whenever I need to gather some extra data, just add some hairs to the for loop. The time complexity is obvious, so is the space complexity (how much data is in memory at any given time), and it's easy to pause and debug. But if you have a bunch of FP combinators and recursion schemas, when the proble…

100% agree with you.

I've always been uneasy with FP-style coding for three reasons:

   - you have strictly no idea how your code will be evaluated by the CPU. Some people love that aspect. It makes me immensely queasy. I might be a control freak.

   - as much as I love the idea an cleanliness of composing functions, having to abandon mutability for that is way too hefty a price to pay. There are situations where overwriting memory is the darndest best way to do things. Yes, side-effects are hard to code with, but just like gotos, there are situations where they are the best solution.

   - I've always felt that FP coders are way too focused the beauty of their code rather that the industrial strength of it, which includes: readability, how easy it is to change, efficiency. Proper production code shouldn't be origami puzzles.

Re: Magical, Mystical JavaScript Transducers

#29
post #19

Earlier quoted context omitted.

For me it's the other way around. A for loop is a general purpose solution that changes continuously with the problem: whenever I need to gather some extra data, just add some hairs to the for loop. The time complexity is obvious, so is the space complexity (how much data is in memory at any given time), and it's easy to pause and debug. But if you have a bunch of FP combinators and recursion schemas, when the proble…

That seems to be such a basic task. Please take it not as me not believing it but could you provide some source about there not being a known O(N) solution for that problem, I'd like to know what the hurdles are and why there might be no solution at all or why finding one is so difficult. (I tried googling it but failed to find something useful)

https://old.reddit.com/r/haskell/comments/3bqlis/how_do_you_...

Found a decent discussion on the matter. Main issue at hand is that its not really FP in question, but datastructures, and more specifically, how far you extend immutability semantics.

In this case, if you forgo immutability requirement, you can trivially mantain semantic purity while still updating the simple array. But with immutability, you can’t construct an array, so you’re locked behind log(n) datastructures

Re: Magical, Mystical JavaScript Transducers

#30
It's so depressing that JavaScript is growing in use, especially when I see articles like TFA. I hate that momentum has allowed a clusterf*ck of a language to become the standard for front end and now one of the top 3 for back-end.

Here's Clojure's explanation of transducers: https://clojure.org/reference/transducers

The whole concept is explained more clearly and with far fewer words and code; and the final result is pretty, or at least clean and tidy.

Post reply on HN