Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Julia, what is the type of an anonymous function when an outer scope is involved?

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.

like image 429
user292301 Avatar asked Oct 12 '25 11:10

user292301


1 Answers

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.

like image 50
Bogumił Kamiński Avatar answered Oct 16 '25 05:10

Bogumił Kamiński



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!