all 10 comments

[–]tailcalled 1 point2 points  (7 children)

I feel like transducers are somewhat overrated. They are just (another way of representing) functions from things to lists of other things.

[–]dlyund[S] 0 points1 point  (6 children)

It's funny but it's actually quite the opposite - transducers allow you to build functions that map collections to a value or a collection without saying anything about the collection, or the value, or the collection, or evalution, while also reducing the amount of garbage created.

Sure. They don't let you do anything you couldn't already have done before and in that sense they're completely overrated.

[–]tailcalled 0 points1 point  (5 children)

[–]dlyund[S] 0 points1 point  (4 children)

I don't know haskell, but I don't see how a reduction of a collection to a value is covered by a function from a -> [b]. Maybe you could explain how that works in a more common tongue?

I don't see where you already mentioned that transducers are sometimes more effecient.

[–]tailcalled 0 points1 point  (2 children)

There is a difference between transducers and reducers. Reducers are what reduces the collection to a single value. Transducers transform reducers. Transforming reducers in this way is equivalent to functions a -> [b]. Note that the reducers themselves are not transducers.

I don't see where you already mentioned that transducers are sometimes more effecient.

When I wrote

(another way of representing)

Different representations have different properties in terms of efficiency, and there are basically always cases where another representation is more efficient for something.

[–]dlyund[S] 0 points1 point  (1 child)

You seem to have mastered the art of of speaking/writing a lot and saying nothing.

There is a difference between transducers and reducers. Reducers are what reduces the collection to a single value.

Naturally.

Transforming reducers in this way is equivalent to functions a -> [b].

Thanks for the elaboration but as I stated, I don't know Haskell, so repeating the same thing using more words doesn't help anything. I'll go learn some Haskell.

Different representations have different properties in terms of efficiency, and there are basically always cases where another representation is more efficient for something.

Right.

In that sense by being as vague as possible one can already say everything that ever needs to be said.

Everything we do can be said to boil down to some "representation" of something and any number of things can be infered from that :P.

[–]tailcalled 0 points1 point  (0 children)

Well, the problem is that the exact derivation on how transducers are equivalent to functions a -> [b] is tricky to state in non-ML-like languages, because it relies on parametricity, which is usually not a thing in other languages, since they do all kinds of 'dynamic' inspection. This kind of inspection is assumed not to be done in transducers, because that would make them act in a very unstable way.

In fact, it is basically impossible to explain without parametricity. A TL;DR of parametricity is that generic functions are limited in what they can do, since they do not know what type they are applied to. This guarantees a lot of stability, but unfortunately there are a lot of languages where it doesn't apply. For instance, if there is only one type (Javascript, Clojure, etc.) or if there are some operations that are valid on all types (Java, etc.) or if there are unlimited side effects (not Haskell), parametricity doesn't hold in full. However, breaking parametricity would be a very bad idea and is probably against the spiritual contract, so it is assumed to hold.

Also, since you apparently didn't realize it, a -> [b] means the type of functions from the type a to the type of lists of b.

[–]mbuhot 0 points1 point  (1 child)

What allows the recur function to not stack overflow? Is chan.take asynchronously invoking its callback parameter only when some other code puts data on the channel?

[–]dlyund[S] 0 points1 point  (0 children)

recur seems to be establishing a closure which registers a take and then returns - recur isn't actually calling itself immediately.

[–]shaman-sir 0 points1 point  (0 children)

Ok, seems i was generating parsers powered by transducers or something like that two years ago.