diff --git a/base/util.jl b/base/util.jl index 0e7087890f81b6..637dd175575a86 100644 --- a/base/util.jl +++ b/base/util.jl @@ -509,6 +509,32 @@ function _kwdef!(blk, params_args, call_args) blk end +""" + @invokelatest f(args...; kwargs...) + +Provides a convenient way to call [`Base.invokelatest`](@ref). +`@invokelatest f(args...; kwargs...)` will simply be expanded into +`Base.invokelatst(f, args...; kwargs...)`. +""" +macro invokelatest(ex) + @assert is_expr(ex, :call) "call expression f(args...; kwargs...) should be given" + + f = first(ex.args) + args = [] + kwargs = [] + for x in ex.args[2:end] + if is_expr(x, :parameters) + append!(kwargs, x.args) + elseif is_expr(x, :kw) + push!(kwargs, x) + else + push!(args, x) + end + end + + esc(:($(GlobalRef(Base, :invokelatest))($(f), $(args...); $(kwargs...)))) +end + # testing """ diff --git a/doc/src/base/base.md b/doc/src/base/base.md index b75453f9074e45..e70f7dab4b633b 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -234,6 +234,7 @@ Base.hasmethod Core.applicable Core.invoke Base.invokelatest +Base.@invokelatest new Base.:(|>) Base.:(∘) diff --git a/test/misc.jl b/test/misc.jl index 62caf29aa75711..70af5595b1074b 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -647,6 +647,31 @@ let foo() = begin @test foo() == 1 end +module atinvokelatest +f(x) = 1 +g(x, y; z=0) = x * y + z +end + +let foo() = begin + @eval atinvokelatest.f(x::Int) = 3 + return Base.@invokelatest atinvokelatest.f(0) + end + @test foo() == 3 +end + +let foo() = begin + @eval atinvokelatest.f(x::Int) = 3 + return Base.@invokelatest atinvokelatest.f(0) + end + @test foo() == 3 + + bar() = begin + @eval atinvokelatest.g(x::Int, y::Int; z=3) = z + return Base.@invokelatest atinvokelatest.g(2, 3; z=1) + end + @test bar() == 1 +end + # Endian tests # For now, we only support little endian. # Add an `Sys.ARCH` test for big endian when/if we add support for that.