Julia: Better syntax for method specification and callable methods

Created on 7 Nov 2019  Â·  5Comments  Â·  Source: JuliaLang/julia

It'd be really nice if the syntax cos(::Float64) to refer to the method directly. That way we could do things like code_typed(cos(::Float64)) instead of code_typed(cos, Tuple{Float64}).

We already use the syntax bar(::T) for the purposes of show ing methods sometimes and it's currently a syntax error to write cos(::T), so it would be both consistent and non-breaking.

Obviously this currently wouldn't be of much utility since we don't have a lot of ways to interact with methods directly. However, in the future, one could imagine a world where methods are directly callable and could take the role of FunctionWrappers.jl. Hence, cos(::Real)(10.0) would be equivalent to invoke(cos, Tuple{Real}, 10.0).

For instance, if someone wants to write a function that takes in another function as an argument and they want to dispatch on whether that function takes in two arguments or one argument, they'd have to ask their user to provide something like a FunctionWrapper instead of a plain old function, so a user would write foo(FunctionWrapper{T, R}(bar)) and foo(FunctionWrapper{Tuple{T, U}, R}(baz)) respectively, but instead with this syntax, it could be something like foo(bar(::T)) and foo(bar(::T, ::U)).

julep speculative types and dispatch

Most helpful comment

So it was realized today on Slack that even though it is a SyntaxError, the syntax actually does parse, so this could be a macro without parser changes:

macro method(ex::Expr)
    @assert ex.head == :call
    Ts = map(ex.args[2:end]) do arg::Expr
        @assert arg.head == :(::) 
        @assert length(arg.args) == 1
        arg.args[1]
    end
    out = quote 
        local mlist = collect((methods($(ex.args[1]), Tuple{$(Ts...)})))
        isempty(mlist) && error("No methods matching $($(QuoteNode(ex)))")
        mlist[end]
    end
    esc(out)
end

@method sin(::Real)

#+RESULTS:
: sin(x::Real) in Base.Math at special/trig.jl:53

one thing that would be solved by doing this with a macro is that @tkf's question regarding ambiguity would be solved without writing f(::) (which is still a syntax error):

f() = 1
@method f()

#+RESULTS:
: f() in Main at In[34]:16

All 5 comments

That is definitely an interesting syntax proposal. It's great that the syntax is available.

they want to dispatch on whether that function takes in two arguments or one argument

But that also implies that Method objects would have types that reflect the number of arguments they accept, which is taking this in a rather different direction.

But that also implies that Method objects would have types that reflect the number of arguments they accept, which is taking this in a rather different direction.

Right, I had forgotten that. I assume it would be onerous / unwanted to parameterize a Method on it's sig, i.e. have

julia> typeof(+(::Bool, ::Bool))
Method{Tuple{typeof(+), Bool, Bool}}

?

Doesn't it make the syntax f() ambiguous? But I guess it is totally reasonable and intuitive to interpret it as the normal function call. To get the method for zero-arg function, I suppose f(::Vararg{Union{},0}) or even f(::Union{}...) would work.

Doesn't it make the syntax f() ambiguous?

That's a good point. It's kinda ugly, but maybe it could just be f(::) since that is also a syntax error currently.

So it was realized today on Slack that even though it is a SyntaxError, the syntax actually does parse, so this could be a macro without parser changes:

macro method(ex::Expr)
    @assert ex.head == :call
    Ts = map(ex.args[2:end]) do arg::Expr
        @assert arg.head == :(::) 
        @assert length(arg.args) == 1
        arg.args[1]
    end
    out = quote 
        local mlist = collect((methods($(ex.args[1]), Tuple{$(Ts...)})))
        isempty(mlist) && error("No methods matching $($(QuoteNode(ex)))")
        mlist[end]
    end
    esc(out)
end

@method sin(::Real)

#+RESULTS:
: sin(x::Real) in Base.Math at special/trig.jl:53

one thing that would be solved by doing this with a macro is that @tkf's question regarding ambiguity would be solved without writing f(::) (which is still a syntax error):

f() = 1
@method f()

#+RESULTS:
: f() in Main at In[34]:16
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tkoolen picture tkoolen  Â·  3Comments

StefanKarpinski picture StefanKarpinski  Â·  3Comments

manor picture manor  Â·  3Comments

omus picture omus  Â·  3Comments

dpsanders picture dpsanders  Â·  3Comments