I can create an anonymous function within a list comprehension in Julia. I expect that this would create a type of Vector{Function}
. Instead, the type is something like Vector{var"#2#4"}
.
For example, when involving an outer scope with an anonymous function
typeof(x->x) <: Function # true
a = 1
typeof(x-> x + a) <: Function # false
while
f(x) = x
typeof(f) <: Function # true
a = 1
g(x) = x + a
typeof(g) <: Function # true
Why is the anonymous function typed differently than the regular function when the outer scope is involved?
Now, in a list comprehension:
typeof([x->x, x->x]) <: AbstractVector{Function} # true
typeof([x->x+i for i in 1:2]) <: AbstractVector{Function} # false
typeof([x->x for i in 1:2]) <: AbstractVector{Function} # false
whether or not the index i
is involved. I initially expected true
in each case.
First note that your initial example is not correct, as you have:
julia> typeof(x->x) <: Function # true
true
julia>
julia> a = 1
1
julia> typeof(x-> x + a) <: Function
true
So both anonymous functions have a type that is a subtype of Function
.
Now as for comprehension note that this is mostly unrelated with the presence of parameter, as you have:
julia> typeof([x->x, x->x]) <: AbstractVector{Function}
true
julia> typeof([x->x]) <: AbstractVector{Function}
false
julia> typeof([x->x for i in 1:2]) <: AbstractVector{Function}
false
The reason for this behavior is when you write something like [...]
then Julia picks a narrow element type of the comprehension (if it did not try to do so you would have Any
element type - the behavior that Python have for its standard lists).
So now how to solve your issue.
To make sure that comprehension has element type of Function
you need to write:
julia> typeof(Function[x->x]) <: AbstractVector{Function}
true
julia> typeof(Function[x->x for i in 1:2]) <: AbstractVector{Function}
true
See also here and here in the manual where it explains how element type for a result of a comprehension and an array literal is picked.
If you omit the Function
prefix the element type is narrower, and in this case the proper subtyping condition would be as follows:
julia> typeof([x->x]) <: AbstractVector{<:Function}
true
julia> typeof([x->x for i in 1:2]) <: AbstractVector{<:Function}
true
(note the extra <:
).
This behavior is related to the fact that in Julia such parametric types are invariant, which is explained here in the Julia manual.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With