Inconsistent errors when creating compact style functions/lambdas with type parameters and return types

I sometimes use the return type feature in Julia, and I have noticed that it is only properly available in the full function style:

For instance I can define:

function test(x::T, x::T)::T where {T}
  return x*exp(y)
end
# test (generic function with 1 method)

If I try to define the compact version I get this error:

test(x::T, y::T)::T where {T} = x*exp(y)
# ERROR: UndefVarError: T not defined

I can however define it with an explicit type:

test(x::Float64, y::Float64)::Float64 = x*exp(y)
# test (generic function with 2 methods)

To make things more interesting I can define the anonymous function:

test = (x::Float64, y::Float64) -> x*exp(y)
#4 (generic function with 1 method)

But if I try to define a return type I get an error:

test = (x::Float64, y::Float64)::Float64 -> x*exp(y)
# ERROR: syntax: invalid argument destructuring syntax "(x::Float64, y::Float64)"

and I can not have explicit where qualified type parameters

test = (x::T, y::T) where {T} -> x*exp(y)
# ERROR: syntax: invalid variable expression in "where"

With “full” anonymous function I get the same errors for different reasons, for example:

test = function (x::Float64, y::Float64)::Float64
  x*exp(y)
end
# ERROR: syntax: expected "(" in function definition

It’s not exactly urgent because I mainly use full function declarations, just an observation and I wonder if it will be fixed at some stage. I am using Julia Version 1.3.0-rc4.1.

Thanks

Your first example is just a matter of parsing precedence–the where T is binding as ::(T where {T}) rather than binding to the whole function declaration. You can get around this with more parentheses:

julia> (test(x::T, y::T)::T) where {T} = x * exp(y)
test (generic function with 1 method)

julia> test(1.0, 2.0)
7.38905609893065

You can see this by just asking Julia to print the expression for you:

julia> expr = quote
         test(x::T, y::T)::T where {T} = x*exp(y)
       end

which yields:

quote
    #= REPL[6]:2 =#
    test(x::T, y::T)::(T where T) = begin
            #= REPL[6]:2 =#
            x * exp(y)
        end                                                                                                                                                                                                                                                                                                                           
end   

And if you want to get really into the weeds, you can call dump(expr) to look at the full expression tree.

2 Likes