FluxML / MacroTools.jl

MacroTools provides a library of tools for working with Julia code and expressions.
https://fluxml.ai/MacroTools.jl/stable/
Other
310 stars 79 forks source link

Allow isdef() to match functions with return types #138

Closed kmsquire closed 4 years ago

kmsquire commented 4 years ago

isdef() doesn't match functions with return types:

julia> using MacroTools

julia> ex1 = :(function foo(a) return a; end);

julia> isdef(ex1)
true

julia> ex2 = :(function bar(a)::Int return 1; end);

julia> isdef(ex2)
false

julia> ex3 = :(f(a) = a);

julia> isdef(ex3)
true

julia> ex4 = :(f(a)::Int = 1);

julia> isdef(ex4)
false

With this PR:


julia> ex2 = :(function bar(a)::Int return 1; end);

julia> isdef(ex2)
true

julia> ex4 = :(f(a)::Int = 1);

julia> isdef(ex4)
true
cstjean commented 4 years ago

This case isn't covered either:

julia> isdef(:(f(x::T) where T = 2))
false

I wonder if there's a clean way to share logic with the splitdef code, because it's very laborious to detect all that may be a function definition.

MikeInnes commented 4 years ago

I think this was written well before return types or where clauses were valid syntax; the number of ways to write a function has really blown up since then :)

There's probably a cleaner way to write this that checks for =/function expressions and then checks for a valid call expression, which would avoid trying to cover every combination explicitly. But this is fine for now, it's a clear improvement.

kmsquire commented 4 years ago

This is probably better:

isdef(ex) = isshortdef(ex) || longdef1(ex) !== nothing
julia> ex1 = :(function foo(a) return a; end);

julia> isdef(ex1)
true

julia> ex2 = :(function bar(a)::Int return 1; end);

julia> isdef(ex2)
true

julia> ex3 = :(function foo(a::T) where T return a; end);

julia> isdef(ex3)
true

julia> ex4 = :(function bar(a::T)::Int where T return 1; end);

julia> isdef(ex4)
true

julia> ex5 = :(function bar(a::S, b::T)::Union{S,T} where {S,T} if rand() < 0.5 return a; end; return b; end);

julia> isdef(ex5)
true

julia> ex6 = :(f(a) = a);

julia> isdef(ex6)
true

julia> ex7 = :(f(a)::Int == 1);

julia> isdef(ex7)
true

julia> ex8 = :(f(a::T) where T = a);

julia> isdef(ex8)
true

julia> ex9 = :(f(a::T)::Int where T = 1);

julia> isdef(ex9)
true

julia> ex10 = :(f(a::S, b::T)::Union{S,T} where {S,T} = rand() < 0.5 ? a : b);

julia> isdef(ex10)
true