JuliaSyntax.jl
JuliaSyntax.jl copied to clipboard
Experiment: Playing with currying, chaining and underscores
A super hacky, quick implementation of "pipefirst / pipelast" ideas inspired by
https://discourse.julialang.org/t/fixing-the-piping-chaining-issue
Tiny demo:
julia> 1:10 />> filter(isodd) />> map(z->z^2)
5-element Vector{Int64}:
1
9
25
49
81
The meaning of />>
is roughly "pipelast", so the above expression is like x |> (y->filter(isodd, y)) |> (y->map(z->z^2, y))
though with different lowering. Similarly />
is "pipefirst".
[Note: in the original version of this PR, />>
was spelled \>
but this is visually confusing.]
Implementation
Parse chains of />
and />>
at the rough same precedence as |>
, treating them as a currying operator for function calls such that the succeeding function call becomes curried with the only free argument as either the first or last, respectively. Thus, the following
x /> f(y) />> g(z)
is parsed as
(chain x (/> (call f y)) (/>> (call g z)))
and lowered to
chain(x, fixbutfirst(f, y), fixbutlast(g, z))
Also, this can be used without data on the left hand side to create a first class data pipeline:
h = /> f(y) />> g(z)
Lowers to
compose_chain(fixbutfirst(f, y), fixbutlast(g, z))
Additionally, add lowering of underscore as strictly tight-binding placeholder syntax. (Super hacky - more forms should be allowed! This is just for experimentation).
Note, I don't really expect to ever merge this, given how difficult https://github.com/JuliaLang/julia/pull/24990 has proven :grimacing:
It's just an experiment for people to play with.
You can try this by checking out this branch and using
JuliaSyntax.enable_in_core!(freeze_world_age=false)
(With this setup, you can also edit JuliaSyntax.jl to play with different lowering scenarios and see them almost immediately in the REPL using Revise. (May need to run a command twice for Revise to pick things up.))