This section on the docs: https://docs.julialang.org/en/v1/manual/types/#Types-of-functions, is very confusing and it kinda contradicts what I think it means (except if I'm wrong, which then would be a result of it not being explained well).
In a paragraph is says:
Types of functions defined at top-level are singletons. When necessary, you can compare them with ===.
I'm assuming "top-level" means "functions that are not nested inside any structure e.g. modules, outer functions, structs, etc." So the function below is top-level:
julia> add(x) = 10 + x
add (generic function with 1 method)
If that's the case then why shouldn't this return true
as being a singleton:
julia> add(2) === add(3)
false
Of course passing the typeof(add)
to the function returns true
:
julia> Base.issingletontype(typeof(add))
true
Now the docs say this in another paragraph:
Types of closures are not necessarily singletons.
The link it placed at closures is this: https://docs.julialang.org/en/v1/manual/functions/#man-anonymous-functions, which I'm assuming it's referring to anonymous functions (even when they aren't closures in their entirety). So this is a closure:
julia> addy = x -> x + 10
#1 (generic function with 1 method)
julia> typeof(addy)
var"#1#2"
So if following what the doc says now, this should return false
but it doesn't:
julia> addy(1) === addy(1)
true
And to add to the confusion, the typeof(addy)
returns true
when passed to Base.issingletontype
:
julia> Base.issingletontype(typeof(addy))
true
I'm confused on all these as things seems to be opposite. I would love to see it better explained and clear my confusion. Moreover the examples on that section trying to explain this contradicts and complicates things. A simpler one straight to the point would be great.
For the first part, with add(2) === add(3)
you are comparing two integers; what is meant by ===
is that you can compare function objects with ===
, e.g. in a "higher-order function" taking an input function f
, you can compare e.g. f
to identity
or to add
with something like if f === add
. Also you can dispatch on typeof(add)
.
For an example of a closure which is not a singleton:
ulia> add(x) = y -> x+y
add (generic function with 1 method)
julia> typeof(add(1)) == typeof(add(2))
true
julia> Base.issingletontype(typeof(add(1)))
false