-
-
Notifications
You must be signed in to change notification settings - Fork 4
pipe
The pipe operator chains function calls by passing the last result as argument to the next call, similar to bash:
2|square|root = root(square(2))
square 2|root = root(square(2))
It is essentially the same as the dot notation in object oriented languages
2.square().root()
2.square.root # if () are optional
The last notation is slightly ambiguous because of ambiguity between (2.square).root
and 2.(square.root)
and the difference between dangling active objects and immediate evaluation 2.square.root()
.
The big difference to the classical dot '.' operation is that piping is an algebraic operation on the function space. Similar to Sum Types, chained functions are assignable objects
printSum := sum|print
printSum 1 2 3
# "6"
If the result is a multi-value or list, naturally it will be passed as list to the next function when applicable or otherwise via broadcast.
The argument to such composed function can appear on the left or right side:
x|f|g := g(f(x))
f|g x := g(f(x))
x (f|g) := g(f(x))
(f|g)(x) := g(f(x))
Pipe sigils '|' and '&' have very similar semantics:
(a|b)(c) := b(a(c))
(a&b)(c) := b(a(c))
While natural for English speakers and beginners, the following syntax is likely unfamiliar for long time programmers:
square & print 2 == print(square(2))
Unfortunately the Natural Language representations of such command chaining is a bit tricky and uses often ambiguous operator 'and' 'comma' and 'then':
wash and rinse the cup, then dry, polish and store it.
Ideally this can someday be parsed as
cup | wash | rinse | dry | polish | store or with cup: wash | rinse | dry | polish | store
It doesn't help that there is some ambiguity confusion about natural language and mathematical and | or.
See monad for abstract handling of optional types and extensions.
Todo: Conceptually clarify potential identity, similarities and differences between dot et pipe . & |
vs
and/or/then/after/before function composition.
With significant-whitespace one could also use the pipe operator to denote lambda functions but that is doubtful.
The pipe operator can be understood to mirror the order of arguments to a function.
x | f := f x == f(x)
would (x)f ever be valid syntax? would it be equivalent to f(x)? would it be desirable?