-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
suggestion: define at-invokelatest macro: #37971
Conversation
75507f8
to
2ebf500
Compare
I made this PR just as a suggestion; if |
I have seen the pattern |
Triage is in favor! It would be nice to factor out the code that transforms |
2ebf500
to
9157b36
Compare
c3faa91
to
c94f949
Compare
Could you kindly provide an example of those transformations ? |
fwiw, I have somewhat same kind of macro """
@invoke f(arg::T, ...; kwargs...)
Provides a convenient way to call [`invoke`](@ref);
`@invoke f(arg1::T1, arg2::T2; kwargs...)` will be expanded into `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)`.
When an argument's type annotation is omitted, it's specified as `Any` argument, e.g.
`@invoke f(arg1::T, arg2)` will be expanded into `invoke(f, Tuple{T,Any}, arg1, arg2)`.
"""
macro invoke(ex)
f = first(ex.args)
argtypes = []
args = []
kwargs = []
for x in ex.args[2:end]
if isexpr(x, :parameters)
append!(kwargs, x.args)
elseif isexpr(x, :kw)
push!(kwargs, x)
else
arg, argtype = isexpr(x, :(::)) ? (x.args...,) : (x, Any)
push!(args, arg)
push!(argtypes, argtype)
end
end
return if isempty(kwargs)
:(invoke($(f), Tuple{$(argtypes...)}, $(args...))) # might not be necessary
else
:(invoke($(f), Tuple{$(argtypes...)}, $(args...); $(kwargs...)))
end |> esc
end I may try to make a PR to introduce |
else | ||
push!(args, x) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the loop is not necessary --- wouldn't just splatting all of ex.args[2:end]
into the expression work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
na, I think the current parser requires the loop to correctly handle keyword arguments, e.g.:
julia> macro invokelatest(ex)
@assert is_expr(ex, :call) "call expression f(args...; kwargs...) should be given"
f = first(ex.args)
args = ex.args[2:end]
return esc(:($(GlobalRef(Base, :invokelatest))($(f), $(args...))))
end
@invokelatest (macro with 1 method)
julia> @macroexpand @invokelatest printstyled(stdout, "blue"; color = :blue)
:(Base.invokelatest(printstyled, $(Expr(:parameters, :($(Expr(:kw, :color, :(:blue)))))), stdout, "blue"))
julia> @invokelatest printstyled(stdout, "blue"; color = :blue)
ERROR: syntax: invalid syntax ; color = :blue
Stacktrace:
[1] top-level scope
@ none:1
c94f949
to
9c93174
Compare
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
9c93174
to
b83c2da
Compare
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
b83c2da
to
3cb45ee
Compare
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
3cb45ee
to
39d118e
Compare
base/util.jl
Outdated
`Base.invokelatest(f, args...; kwargs...)`. | ||
""" | ||
macro invokelatest(ex) | ||
@assert is_expr(ex, :call) "call expression f(args...; kwargs...) should be given" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be an assert; it should throw an ArgumentError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
8360266
to
d3f9cdb
Compare
- offers easier syntax to call `Baes.invokelatest` - `@invokelatest f(args...; kwargs...)` will simply be expanded into `Base.invokelatst(f, args...; kwargs...)`
Co-authored-by: Jeff Bezanson <[email protected]>
d3f9cdb
to
7aa4607
Compare
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
This would be nice to finish off. What's required to make forward progress here? |
I think we can merge this as is ? |
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of #37971
- provides easier syntax to call `Core.invoke`, e.g. `@invoke f(a::Integer)` will be expanded into `invoke(f, Tuple{Integer}, a)` - when type annotation is omitted, the argument type is specified as `Any` Built on top of JuliaLang#37971
Baes.invokelatest
@invokelatest f(args...; kwargs...)
will simply be expanded intoBase.invokelatst(f, args...; kwargs...)