You’d have to define a + method for numbers and strings, e.g.
Base.:+(x::Number, s::AbstractString) = x + parse(Int, s)
Base.:+(s::AbstractString, x::Number) = x + s
However, I would strongly recommend that you not do this:
it is type piracy: you adding a new method to another package’s function with another package’s types. This could have unexpected side-effects on other packages.
Automatic conversion of strings to integers is not idiomatic to Julia, and will confuse anyone reading your code.
What are you actually trying to do here? What is your underlying problem?
The function and all the annotated types don’t belong to you (they belong to Base) so that’s type piracy. Don’t do that.
convert doesn’t automatically happen to inputs of binary operations. That’s promote.
You can parse the string before you call a constructor: X(a=parse(Int64, "1")). You can also define a constructor method for X(;a::String) to do that parsing step before forwarding to X(::Int64, ::Int64). @kwdef won’t help you there, it just does the simplest forwarding without any type annotations:
I read portfolios of trades in from various sources: SQL, CSV, XML…
and convert lots of text fields to enums or other types.
e.g: Put, Call, In, Out, Up, Down, Yes, No, AUD, USD, GBP …
rather than do a manual conversion on every loaded field I’ve written a Base.convert statement for each type.
@enum Up_Down Up Down
@enum In_Out In Out
Base.convert(::Type{<:Enum}, x::AbstractString ) = (eval ∘ Meta.parse)(x)
struct Barrier
up_down::Up_Down
in_out::In_Out
end
Barrier("Up","In")
Barrier( nt.up_down, nt.in_out )
Where nt is a NamedTuple of Strings created from XML or some DataFrame row.
I find this easier than doing a conversion for every struct-field.
I also like to use the constructor short hand within the struct definition. Example b=a+1 in my first message. Unfortunately, this formula is applied before a has been converted to the specified field type.
I was wondering if the order of operations can be changed so that any Base.convert() statement is applied first, and the result is used in any formulas for later fields in the struct.
You’d have to manually add it. Automatic convert to field types occurs for positional arguments of new, thus after anything you do with keyword arguments.
I think your best bet is to forget about convert piracy (anyone using your code will not expect those methods to exist, and the more you pirate, the more likely you break your code in isolation) and use a contextually limited macro to generate the calls or constructor methods you need. By contextually limited, I mean the macro only works under statically unknowable conditions. Using X as an example, you expect a to take a string input, parse it to the type of a, then compute b from the result. What if b = a + 0.5? Then you run into an InexactError at new. What if b = Symbol(a)? You didn’t pirate a convert method to make that work at new. Those examples appear obvious enough to avoid, but generic function calls generally won’t be that predictable.