dfdx
1
f = x -> x + 1
T = typeof(f)
# ==> var"#2#4"
Given a type T
of an anonymous function, can I get that function? I.e. given var#"2#4"
get object f
?
I get the type T
from the lowered representation of code (actually, from IRTools, but it’s nearly the same in this context). E.g.:
@code_lowered (xs -> [x + 1 for x in xs])(rand(5))
# ==> CodeInfo(
# ==> 1 ─ #2 = %new(Main.:(var"#2#4"))
# ==> │ %2 = #2
# ==> │ %3 = Base.Generator(%2, xs)
# ==> │ %4 = Base.collect(%3)
# ==> └── return %4
)
In IR, we have a special instruction %new
which constructs the function, but I can’t find a language or compiler feature to do it from my code.
For singleton types (such as anonymous functions which aren’t closures), you can access the instance from the instance
field:
julia> f = x -> x + 1
#1 (generic function with 1 method)
julia> T = typeof(f)
var"#1#2"
julia> T.instance
#1 (generic function with 1 method)
6 Likes
dfdx
3
Because of context switch I didn’t realize this approach doesn’t work for UnionAll
types like in the example with the generator:
@code_lowered (xs -> [x + 1 for x in xs])(rand(5))
# ==> CodeInfo(
# ==> 1 ─ #130 = %new(Main.:(var"#130#132"))
# ==> │ %2 = #130
# ==> │ %3 = Base.Generator(%2, xs)
# ==> │ %4 = Base.collect(%3)
# ==> └── return %4
# ==> )
T = var"#130#132"
T.instance
# ==> ERROR: type UnionAll has no field instance
T.body.instance
# ==> ERROR: UndefRefError: access to undefined reference
T{:x}.instance
# ==> ERROR: UndefRefError: access to undefined reference
Any directions on how to refer to the underlying function (essentially, x + 1
) in this example?
dfdx
4
After many experiments I came up with the following utility function which can instantiate any objects including anonymous functions:
@generated function __new__(T, args...)
return Expr(:splatnew, :T, :args)
end
Example:
julia> @code_lowered (xs -> [x + 1 for x in xs])(rand(5))
CodeInfo(
1 ─ #58 = %new(Main.:(var"#58#60"))
│ %2 = #58
│ %3 = Base.Generator(%2, xs)
│ %4 = Base.collect(%3)
└── return %4
)
julia> T = var"#58#60"
var"#58#60"
julia> f = __new__(T)
#58 (generic function with 1 method)
julia> f(1)
2
1 Like