I am new to Julia and just learned that Julia can generate generic methods by changing the function signature.
function round_number(x::Float64)
return round(x)
end
round_number(3.1415)
round_number(3)
function round_number(x::Int64)
return x
end
round_number(3)
When I found the function test_interpolated
cannot work with number and string, I tried to see if I can generate a new signature to extend the isless
. Unfortunately, it did not work.
function test_interpolated(a, b)
if a < b
"$a is less than $b"
elseif a > b
"$a is greater than $b"
else
"$a is equal to $b"
end
end
test_interpolated(3.14, 3.14)
test_interpolated(3.14, "3.14")
function isless(x::AbstractFloat, y::AbstractString)
return x < float64(y)
end
test_interpolated(3.14, "3.14")
Did I misunderstand the concept?
CodePudding user response:
First note that there is no float64
function in Julia. To parse a string as a number you need to use the parse
function:
parse(Float64, "3.14")
The second thing in your code is that:
function isless(x::AbstractFloat, y::AbstractString)
return x < float64(y)
end
creates a new function named isless
in your current module (most likely Main
if you are working in e.g. REPL).
To add a method to the isless
function defined in Base
module you would have to write:
function Base.isless(x::AbstractFloat, y::AbstractString)
return x < float64(y)
end
(note the Base.
prefix)
Although Julia allows for it you should never do it in your code. This style is called type piracy, and is explained here.
In short you are adding a method to a function from Base
module and both AbstractFloat
and AbstractString
are also defined in Base
module. The problem is that adding such a method might break other code that assumes in this case that isless
when passed AbstractFloat
and AbstractString
throws an error.
The way you should define your function is e.g. as follows:
toreal(x::Real) = x
toreal(x::AbstractString) = parse(Float64, x)
function test_interpolated(a::Real, b::Real)
if a < b
"$a is less than $b"
elseif a > b
"$a is greater than $b"
else
"$a is equal to $b"
end
end
test_interpolated(a, b) = test_interpolated(toreal(a), toreal(b))
In this way you ensure that you have one specific method with narrow signature implementing the logic for real numbers and other method for test_interpolated
that has a wide signature that performs conversion to appropriate types.
Note that I use Real
not AbstractFloat
as comparison with <
is guaranteed to be defined across two Real
values, and you most likely want your function to e.g. accept integers.
The approach I show is explained here.