Open pdeffebach opened 3 years ago
Yes and the thing is that fun1 \circ fun2
is compiled only once as opposed to x -> fun1(fun2(x))
which has to be compiled every time. but I would label it as a minor improvement.
Actually I had implemented something like that back in 2019 before you cleaned up the package. FWIW, here are the functions I had written:
"""Check whether expression is a single-argument call, like f(x)"""
isoneargcall(e::Expr) =
e.head === :call && length(e.args) == 2 && e.args[1] isa Symbol
function tocomposition(body)
if body.head == :(=) && length(body.args) == 2 &&
body.args[2] isa Expr
funs = Symbol[]
e = body.args[2]
while e isa Expr && isoneargcall(e)
push!(funs, e.args[1])
e = e.args[2]
end
if e isa Symbol || (e isa QuoteNode && e.value isa Symbol)
# Recursion parsed the full expression
return mapreduce(eval, ∘, funs)
else # Expression doesn't consist only in single-argument calls
return body
end
end
return body
end
I think that when we see
fun1(fun2(x))
the function passed totransform
should befun1 \circ fun2
. That way we can take advantage of more fast paths iirc.