Type conversion fails on valid input
paigeweber13 opened this issue · 5 comments
Expected behavior: on supplying 0.5
for an arugment which requires Real
, ArgParse
should accept this.
Actual behavior: ArgParse
produces an error that reports "invalid argument"
Minimal reproducible example:
test_function.jl
:
using ArgParse
function main(args)
s = ArgParseSettings("some function")
@add_arg_table! s begin
"x"
arg_type = Real
default = 0.5
help = "input"
end
parsed_args = parse_args(args, s)
println("Parsed args:")
for (key,val) in parsed_args
println(" $key => $(repr(val))")
end
end
main(ARGS)
runing with julia test_function.jl 0.5
produces the following output:
invalid argument: 0.5 (conversion to type Real failed; you may need to overload
ArgParse.parse_item; the error was: MethodError(tryparse, (Real, "0.5"), 0x0000000000006a06))
usage: Bifurcation.jl [x]
However, in an open julia session I can write Real(0.5)
with no problems.
Platform information:
- OS: KDE Neon (ubuntu based) 18.04
- Julia: 1.4.1
I noticed that if I remove the line arg_type = Real
and run the same command, I get the output x => "0.5"
which implies that the argument is input as a string. Is the string not getting parsed?
The issue here is that arguments are parsed as strings, and in order to transform them into Julia types they need to be parsed. For numeric types, ArgParse tries to leverage a standard Julia function, parse
, which however is only defined on concrete types. When you call it with an abstract type like Real, it's ambiguous, since it's unclear which type of Real you actually want to get. We could add defaults, but frankly I just took a look at the code and it would be rather messy and brittle. Would it be reasonable in your code to simply use Float64
as a type, or do you really need a more generic Real
? If so, what's your use case?
Sure, I can use Float64
. I should have mentioned this at first, but I'm new to Julia and that could be part of the issue. I was trying to follow the section of the style guide "Avoid writing overly-specific types", but for my specific case the specific type is fine.
I see. That advice applies mostly to function arguments though, in the context of ArgParse allowing generic Reals in an argument would hardly give any benefit with respect to Float64
. There might be cases (e.g. if one wants to allow the user to provide large-precision numbers, rationals, "exotic" numbers defined in other packages etc, and deal with each of them appropriately) but I feel that it would be very hard to come up with generic rules that fit all possible scenarios of this kind. So in such cases the advice given by the error message, to overload ArgParse.parse_item
, is probably the best way to go, since it allows to define the interface behavior precisely, on a case-by-case basis.
Thanks for your comments and advice on an "issue" that turned out not to be an issue haha. What you said makes sense; if you have a specific use-case that requires exotic types, it makes sense to just overload ArgParse.parse_item
yourself.