Others just use a REPL instead, where tr, sort, uniq, and sed get to be function calls with a threading macro.
Others just use a REPL instead, where tr, sort, uniq, and sed get to be function calls with a threading macro.
A chariot in the age of cars.
A rideable horse in the age of broken, disparate, infrastructure.
But, at the end of the day, it all depends on what you're trying to accomplish. I use repls, shells, notebooks, etc, on a regular basis. Unix tools solve some problems. Repls solve other problems. Notebooks another. What's important, to me, is to be able to be able to make the most out of them all, despite their flaws, because they're simply the tools that we have in our toolchain. It would be a shame to not learn our own tools, when they can offer us so, so much.
The UNIX shell is just a primitive REPL.
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.
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) This is the TXR Lisp interactive listener of TXR 232.
Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
1> [(opip (open-file "/etc/fstab")
(record-adapter #/[^A-Za-z]+/)
get-lines
sort-group
(sort @1 greater len)
(take 10)
(mapcar [juxt car len]))]
(("defaults" 5) ("a" 3) ("dev" 3) ("ext" 3) ("home" 3) ("opt" 3)
("UUID" 2) ("c" 2) ("d" 2) ("e" 2))
Pretty print the list obtained from prompt 1: 2> (mapdo (do put-line `@(car @1) -> @(cadr @1)`) *1)
defaults -> 5
a -> 3
dev -> 3
ext -> 3
home -> 3
opt -> 3
UUID -> 2
c -> 2
d -> 2
e -> 2
nil