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))
.
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
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:
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):