Is there a simple and standard way to deprecate a keyword argument? From reading through past threads it sounds like you need to do this manually, e.g., Deprecate keyword argument. But surely there’s a nice macro for this somewhere?
Here’s the syntax I am looking for to deprecate a
in favor of the new kw b
:
function f(; @deprecate_kw(a, b=2))
return b
end
f(a=2) # Works, but raises a depwarn
f(b=2) # Also works
Here’s a simple attempt which works without needing to wrap the entire function signature. However, I don’t like this because:
- I still need to pass
deprecated_kw=nothing
.- Aside: Is there any way to generate multiple keywords using a macro that is used inline in the function signature?
- The
depwarn
doesn’t know the function.- Aside: I tried calling
stacktrace(backtrace())
from within the kwcall to get the function name, but it seemed too hacky.
- Aside: I tried calling
- Code analyzers like the one used in VSCode do not know about the new keyword.
(expand)
macro deprecate_kw(deprecated_kw, new_kw)
return _deprecate_kw(deprecated_kw, new_kw) |> esc
end
function _deprecate_kw(deprecated_kw::Symbol, new_kw::Expr)
@assert(new_kw.head == :(=), "Must pass a simple assignment expression.")
default_value = new_kw.args[2]
depwarn_string = "The keyword argument $(deprecated_kw) is deprecated in favor of $(new_kw.args[1])."
new_kw.args[2] = quote
if $deprecated_kw != nothing
# Get function name to put in depwarn:
Base.depwarn($depwarn_string, :nothing)
$deprecated_kw
else
$default_value
end
end
return Expr(:kw, new_kw.args[1], new_kw.args[2])
end
Then I can use this with:
function f(;
a=nothing, @deprecate_kw(a, b=2),
c=nothing, @deprecate_kw(c, d=3),
)
return b + d
end
with outputs (under julia --depwarn=yes
):
julia> f(a=2)
┌ Warning: The keyword argument a is deprecated in favor of b.
│ caller = ip:0x0
└ @ Core :-1
5
julia> f(b=2)
5
Is there a better way to do this? Or is manually swapping argument values in the function body the only way?
Here's the macro expansion for clarity:
julia> @macroexpand @deprecate_kw(a, b=2)
:($(Expr(:kw, :b, quote
if a != nothing
Base.depwarn("The keyword argument a is deprecated in favor of b.", :nothing)
a
else
2
end
end)))