Not really no.
I see what you are getting at, and I like it, but it is not possible.
(Certainly not currently, possibly not ever. Maybe oneday using traits.)
Lets look at an example: foo
and bar
julia> foo(x::String) = println(x)
foo (generic function with 1 method)
julia> foo(x::Int64) = println(x+1)
foo (generic function with 2 methods)
julia> bar(x...) = println(x)
bar (generic function with 1 method)
What is the type hierarchy for foo
?
julia> typeof(foo)
#foo
julia> supertype(typeof(foo))
Function
julia> supertype(supertype(typeof(foo)))
Any
So we see that they type of the foo
function is a #foo
which is a subtype of Function
. Note that #
means this is a generated name, you can't put hash's in names when just writing code, but the julia compiler (using the term loosely) can.
Why isn't its super-supertype more specific, than just function?
What would it be? Function{Int64}
or Function{String}
?
Functions in julia, do not have type-signatures, Methods do.
A function is just a name for multiple dispatch, a method is actually what is dispatched to. Roughly speaking the function name says which table should i look in, and the types of the arguments (ie it's type signature) are the key for looking up, in that table. The method itself is what is returned, using that key.
So lets continue with our example and see what we can do:
julia> dothing(f::typeof(foo)) = f(rand([randstring(), rand(Int64)]))
dothing (generic function with 1 method)
julia> dothing(foo)
3139374763834167054
julia> dothing(foo)
Ed2kNGrd
julia> dothing(bar)
ERROR: MethodError: no method matching dothing(::#bar)
Closest candidates are:
dothing(::#foo) at REPL[11]:1
So we have sucessfully restricted dothing
, to only take a #foo
as its arguement. See it throws an error when you give it a #bar
.
This isn't really useful since the foo
function is the only thing of type #foo
.
We could use a Union
though:
julia> dootherthing(f::Union{typeof(foo),typeof(bar)}) = f(rand([randstring(), rand(Int64)]))
dootherthing (generic function with 1 method)
julia> dootherthing(foo)
9107791406050657562
julia> dootherthing(foo)
SmB2Xmw8
julia> dootherthing(bar)
("1IpZIMnx",)
julia> dootherthing(bar)
(-6356894350805213697,)
julia> dootherthing(str)
ERROR: UndefVarError: str not defined
julia> dootherthing(string)
ERROR: MethodError: no method matching dootherthing(::Base.#string)
Closest candidates are:
dootherthing(::Union{#bar,#foo}) at REPL[19]:1
dootherthing
accepts a #foo
or a #bar
.
Either function works.
This has limited applications, as a whitelist.