Fixing the Piping/Chaining/Partial Application Issue (Rev 2)

Indeed, measuring compile time is a difficult thing to do. I detailed my misadventures with it in this post.

The runtime of this function is basically instantaneous, which you can confirm using @btime (a proper measurement will show single-digit nanoseconds)—so even though compile time and runtime are inseparable, the runtime is negligible in this measurement.

I force Base.Fix1 to recompile by redefining the anonymous function every time. You can see that it’s a new function each time:

julia> f = (x,y) -> x+y; (f, typeof(f))
(var"#1#2"(), var"#1#2")

julia> f = (x,y) -> x+y; (f, typeof(f))
(var"#3#4"(), var"#3#4")

julia> f = (x,y) -> x+y; (f, typeof(f))
(var"#5#6"(), var"#5#6")

This makes anonymous functions an excellent stimulus for measuring these compile times, because a new anonymous function will have a different type despite behaving exactly the same as before.

Chain.jl has been a huge inspiration for how this proposal should work. :ok_hand: I pretty much copypasted it in imagining the behavior of -- call chain syntax, except that I decided to localize variable scope within the chain using let statements instead of making unique variables at the parent scope with gensym. This enables me to use it as a local keyword, but it makes it difficult to create side-effects except by calling functions which have side-effects.