4 ms·
Transducers are kind of an abstraction level above what you're describing. Transducers don't care about the medium / collection / stream. The algorithm of your
by pi-rat 11y ago
Transducers are kind of an abstraction level above what you're describing. Transducers don't care about the medium / collection / stream. The algorithm of your transformation is decoupled from the data structure, and completely reuseable.
Clojure used to have (/is deprecating) what you're describing. It's being replaced by transducers to avoid having to implement the same functionality whenever there's a new paradigm/idea. I.e this week we're doing lazy seqs, the next CSP or streams - the transducer logic stays the same.
- Veedrac 11y ago> It's being replaced by transducers to avoid having to implement the same functionality whenever there's a new paradigm/idea. I.e this week we're doing lazy seqs, the next CSP or streams - the transducer logic stays the same. AFAICT, iterator adapters don't require you to reimplement the "transducer logic" any more than transducers do. You implement a transformation into an iterator (eg. IntoIterator) and from an iterator (eg. FromIterator) and use the standard transformations on the iterators. Since a transducer is like an iterator adapter, one is comparing these to functions Iterator<A> → Iterator<B>, which can be passed around and reused as first class citizens with no more difficulty than any other object. I'm not sure, but one difference might be that you can't give a chunk of stuff to an iterator adaptor and say "run as much of this as possible, and then suspend". Iterators are inherently pull-based, so instead you say "I want X values". I can imagine the former being more useful in some cases where the producer is deciding when computation should be performed.
- gue5t 11y agoIterator adaptors such as .filter, .flat_map, etc. are all defined with no reference to/knowledge of the iterators they work on: http://doc.rust-lang.org/std/iter/trait.Iterator.html http://doc.rust-lang.org/std/iter/trait.Iterator.html They take a stream of values (i.e., an iterator, which is really only enough state to produce the stream, but not an actual collection of the values produced by that stream) and give you a different stream back, e.g. one that looks like the original stream with a function applied to each element or certain elements removed. Rust iterators are "lazy", and iterator adaptors maintain this property.
- kybernetikos 11y agoThey also assume that they can always draw from their source iterator if they are called on to produce a value, which means that anything you write for them will not be reusable in scenarios where this isn't true. Transducers don't have this problem.
- gue5t 11y agoCan you describe some situations in which this problem comes up? I'm having a hard time imagining when I would want/expect an iterator adaptor that does something useful on an empty/finished input.
- kybernetikos 11y agoIt's not so much empty/finished, it's that values are produced at particular times, perhaps as the user clicks the mouse, or as messages come in from the network or over stdin. Maybe you're writing some web page analytics software. Let's say you've got a stream of values representing the (x,y) positions of mouse clicks, you want to filter out any that are more than a predefined distance from a particular point, then remove any that occur 200ms or less than the last one, then every time you have 10 of them you want to post them to the server. How would you do this with iterator adaptors? With transducers, the exact same filter that removes points further than a particular distance away in the event stream can be used on any source (e.g. an iterator).