3 ms·
isn’t the first thing you are being the first thing evaluated just better? we read ltr, so having to see and remember a before c(d) but then having some of a’s
by grapist420 5y ago
isn’t the first thing you are being the first thing evaluated just better? we read ltr, so having to see and remember a before c(d) but then having some of a’s arguments at the very end is just annoying vs pipes
- fiddlerwoaroof 5y agoIt's hard for me to verbalize, but the rtl composition just sort of makes sense. For one thing, it's the way functions already sort of work: a(b(c(d))) === (a • b • c)(d) // the functions are in the same order And, when you think about the typical order of evaluation, a(b(c(d, e, f))) is evaluated: - look up the value of d, e and f - evaluate c(d, e, f) (call it g) - evaluate b(g) (call it h) - evaluate a(h) (call it i) - return i Pipes add an inconsistency between the order of evaluation of arguments vs. function calls and the order of evaluation of functions. (Also, completely separately, I've mostly come around to disliking operators and thinking Lisps are right here: precedence and associativity are "intuitive" for basic math operators because we've spent years studying math and getting used to PEMDAS, but anything beyond this is just asking for trouble: aside, maybe, from APL/J's strict right-associativity without precedence)
- hanche 5y agoI have an algebra book on my shelf* that puts function arguments on the left, as in (x)f instead of the usual f(x). It is definitely more “natural”, as functions compose in the normal reading direction. But even so, it is increadibly hard to read, because the break with the usual convention is so radical. Needless to say, it didn’t catch on. * In my office, but I am at home. Don’t remember the author; sorry. But it was written back in the ‘60s, I think.
- grapist420 5y agothat same logic works for reversed-compose - a|b|c|d = (a)|(b~c~d). It is inconsistent with the normal kind but I think it’s worth it just for the ability to write list |map| func |filter| predicate |group-by| keyfunc |map| .values() |map| sum, which is so nice because you start with the value and as you read the thing that’s happening is precisely the thing you’re reading, and everything’s in one place - it’s
- fiddlerwoaroof 5y agoThis is only true if your stages don't have arguments: with a | b(something) | c | d, `something` is now evaluated before b(something)
- grapist420 5y agotrue, although argument evaluation order in a(x,b(y,c(d),z),w) is already somewhat hard to rely on
- isaacimagine 5y agoWhat I like about pipes it that it allows two ways to write chains of function calls. For calls that are more branch-like, the nested structure of standard function calls makes the most sense to me: article = create(author("John"), Page.article()) For cases where you're modifying data sequentially, the pipe structure makes it really easy to read: 5th_prime = 0.. | filter(is_prime) | nth(5) Having a way to write function calls forwards and backwards lets you choose whatever syntax feels most appropriate for the job.