I have a config object like this:
using Parameters
@with_kw mutable struct Config
"Param 1"
param1::Float64
# ... several other items ...
"Whether to iterate randomly."
use_random::Bool = false
end
And now I need to modify it like so, to enable more than 2 strategies:
@with_kw mutable struct Config
"Param 1"
param1::Float64
# ... several other items ...
"Strategy for iteration, one of 'random' or 'baseline'."
iter_strategy::String = "random"
end
But this is a breaking change to its definition, so I want to give some deprecation help to the user.
Is there some way I can intercept existing calls to the keyword-based constructor generated by @with_kw
, changing a use_random
setting to the appropriate iter_strategy
value, and issuing a warning that the caller should change their code? Existing callers would have code like Config(param1=1.1, use_random=true)
or similar.
Thanks.
FYI this is very similar to Catching deprecated keyword arguments (with Parameters.jl), which doesn’t currently have an answer.
Not sure if that works for your non-MWE, but this is what I (got the ping from the linked post) ended up using:
@kwdef mutable struct Config
"""Param 1"""
param1::Float64
"""Deprecated, please use `iter_strategy = "random"` instead."""
use_random::Union{Bool, Nothing} = nothing
"""Strategy for iteration, one of `random` or `baseline`."""
iter_strategy::String = (isnothing(use_random) || use_random) ? "random" : "baseline"
end
Config(; param1 = 1.0, use_random = true) # Config(1.0, true, "random")
Config(; param1 = 1.0, use_random = false) # Config(1.0, false, "baseline")
Config(; param1 = 1.0) # Config(1.0, nothing, "random")
Config(; param1 = 1.0, iter_strategy = "baseline") # Config(1.0, nothing, "baseline")
Config(; param1 = 1.0, iter_strategy = "random") # Config(1.0, nothing, "random")
If you can live with the type change (and the union) as “non-breaking” for the outside, then this might be a “workaround”.
EDIT: You could of course make the default initialization more complex, e.g., catching and preventing that a user passes both arguments.
Yeah, I don’t love having the union of the fields in there, it creates some confusion in users of the Config
object since both fields are still there. I’d prefer to take care of everything before/while creating the object and have no use_random
field left.
FWIW I didn’t find a great solution to this at the constructor point, I ended up finding all the places in my code where a constructor is called and adjusting the calls there.
If there were a way to call the @with_kw
-generated constructor from a new constructor, that would be a great way to fix this in one spot for all callers.