GuiTaek
GuiTaek

Reputation: 484

How to pass a function typesafe in julia

Let's say, I want to pass a function to another function:

function foo()
    return 0;
end
function bar(func)
    return func();
end
print(bar(foo));

But you can make functions typesafe:

function func(t::Int)
    print(t);
end
func(0);                 #produces no error
func("Hello world");     #produces an error

I didn't found out, how I combine both, that means, how can I explicitly define a parameter of bar, like func, to be a function, possibly with certain input / output argument types.

Thanks in advance for any help.

Upvotes: 6

Views: 1231

Answers (2)

fredrikekre
fredrikekre

Reputation: 10984

If I understand you correctly you want to make sure the passed function returns a specific type? The simplest thing is to just typeassert the return value at runtime:

julia> function f(func)
           val = func()::Int # Error if the return value is not of type Int
           return val
       end
f (generic function with 1 method)

julia> f(() -> 1)
1

julia> f(() -> 1.0)
ERROR: TypeError: in typeassert, expected Int64, got Float64
Stacktrace:
 [1] f(::var"#7#8") at ./REPL[5]:2
 [2] top-level scope at REPL[8]:1

Alternatively you can use the FunctionWrappers.jl package (which will convert to the specified return type, or error if the conversion is not possible):

julia> using FunctionWrappers: FunctionWrapper

julia> function f(func::FunctionWrapper{Int,<:Tuple})
           val = func()
           return val
       end;

julia> function f(func)
           fw = FunctionWrapper{Int,Tuple{}}(func)
           return f(fw)
       end;

julia> f(() -> 1)
1

julia> f(() -> 1.0) # Can convert to Int
1

julia> f(() -> 1.2) # Can not convert to Int
ERROR: InexactError: Int64(1.2)

Upvotes: 4

Jakob Nissen
Jakob Nissen

Reputation: 1991

A function is of type Function. You can easily check this:

julia> foo() = 1;

julia> T = typeof(foo)
typeof(foo)

julia> supertype(T)
Function

julia> foo isa Function
true

This will not necessarily cover all callable types, as you can make any type callable:

julia> struct Callable end

julia> (::Callable)(x::Number) = x + one(x)

julia> callable = Callable()
Callable()

julia> callable(5)
6

julia> callable isa Function
false

Upvotes: 3

Related Questions