42 ms·
The threading macro just represents function composition, while a Unix pipe represents buffered streaming I/O (or composition of dataflow operators, if you like
by senderista 7y ago
The threading macro just represents function composition, while a Unix pipe represents buffered streaming I/O (or composition of dataflow operators, if you like). Two related but quite different things.
- pjmlp 7y agoFunction composition can make use of any kind of streaming, better yet, with a debugger at disposal. The UNIX shell is just a primitive REPL.
- samatman 7y agoIt can, but only at the cost of complecting source and sink. By default, function composition is eager: a function is expected to do its work, and hand the whole return value off to the next function. We can make this lazy, by setting up an iterator and handing this off. At some expense: our next function must expect an iterator, and therefore can't handle a full data structure. At minimum it must coerce those into an iterator when encountered. Also, it gets awkward to reason about iterators wrapped in iterators wrapped in iterators, even with a debugger, you get action at a distance, where the fourth function in your thread is failing because the first iterator of three has a flaw in it. Shell pipes handle all of this for the user, with sensible defaults which can be overridden and modified for special cases. It's a powerful abstraction and I wish more languages offered something like it.
- kazinator 7y agoLaziness doesn't require iterators; it can be based on lazy data structures such as lazy lists. This is the TXR Lisp interactive listener of TXR 232. Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet. 1> (defvar N (range 1)) N 2> (take 5 N) (1 2 3 4 5) 3> (typeof N) lcons 4> (set (car N) 42) 42 5> (take 10 N) (42 2 3 4 5 6 7 8 9 10)