Tarik
Tarik

Reputation: 11209

Declare a Julia function that returns a function with a specific signature

How can I declare a Julia function that returns a function with a specific signature. For example, say I want to return a function that takes an Int and returns an Int:

function buildfunc()::?????
   mult(x::Int) = x * 2
   return mult
end

What should the question marks be replaced with?

Upvotes: 4

Views: 742

Answers (2)

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

One thing needs to be made clear. Adding a type declaration on the returned parameter is just an assertion, not part of function definition. To understand what is going on look at the lowered (this is a pre-compilation stage) code of a function:

julia> f(a::Int)::Int = 2a
f (generic function with 1 method)

julia> @code_lowered f(5)
CodeInfo(
1 ─ %1 = Main.Int
│   %2 = 2 * a
│   %3 = Base.convert(%1, %2)
│   %4 = Core.typeassert(%3, %1)
└──      return %4
)

In this case since the returned type is obvious this assertion will be actually removed during the compilation process (try @code_native f(5) to see yourself).

If you want for some reason to generate functions I recommend to use the @generated macro. Be warned: meta-programming is usually an overkill for solving any Julia related problem.

@generated function f2(x)
    if x <: Int
        quote
            2x
        end
    else
        quote
            10x
        end
    end
end

Now we have a function f2 where the source code of f2 is going to depend on the parameter type:

julia> f2(3)
6

julia> f2(3.)
30.0

Note that this function generation is actually happening during the compile time:

julia> @code_lowered f2(2)
CodeInfo(
    @ REPL[34]:1 within `f2'
   ┌ @ REPL[34]:4 within `macro expansion'
1 ─│ %1 = 2 * x
└──│      return %1
   └
)

Hope that clears things out.

Upvotes: 3

Patates
Patates

Reputation: 74

You can use Function type for this purpose. From Julia documentation:

Function is the abstract type of all functions

function b(c::Int64)::Int64
        return c+2;
    end

function a()::Function
        return b;        
    end

Which prints:

julia> println(a()(2));

4

Julia will throw exception for Float64 input.

   julia> println(a()(2.0)); 

ERROR: MethodError: no method matching b(::Float64) Closest candidates are: b(::Int64)

Upvotes: 3

Related Questions