我是 Julia 的新手,刚刚了解到 Julia 可以通过更改函数签名来生成泛型方法。
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)
当我发现函数 test_interpolated
无法处理数字和字符串时,我尝试查看是否可以生成一个新的签名来扩展 isless
。不幸的是,它没有用。
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")
我是不是误解了这个概念?
最佳答案
首先注意没有float64
在 Julia 中发挥作用。要将字符串解析为数字,您需要使用 parse
功能:
parse(Float64, "3.14")
代码中的第二件事是:
function isless(x::AbstractFloat, y::AbstractString)
return x < float64(y)
end
创建一个名为 isless
的新函数在您当前的模块中(很可能是 Main
如果您正在使用 REPL)。
将方法添加到 isless
Base
中定义的函数您必须编写的模块:
function Base.isless(x::AbstractFloat, y::AbstractString)
return x < float64(y)
end
(注意 Base.
前缀)
尽管 Julia 允许这样做,但您永远不应该在代码中这样做。这种风格被称为类型盗版,解释为here .
简而言之,您正在向 Base
中的函数添加一个方法。模块和两者 AbstractFloat
和 AbstractString
也在 Base
中定义模块。问题是添加这样的方法可能会破坏在这种情况下假定 isless
的其他代码。当通过 AbstractFloat
和 AbstractString
抛出错误。
你应该定义你的函数的方式是例如如下:
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))
通过这种方式,您可以确保您拥有一个具有窄签名的特定方法来实现实数的逻辑,而其他方法则用于 test_interpolated
。具有广泛的签名,可以执行到适当类型的转换。
请注意,我使用 Real
不是AbstractFloat
与 <
比较保证跨两个 Real
定义值(value)观,你很可能希望你的功能,例如接受整数。
我展示的方法有解释 here .
编辑
调度歧义的例子。使用全新的 Julia 1.7.0 session :
julia> struct T end
julia> Base.propertynames(::T, ::Integer) = nothing
julia> propertynames(T(), true)
ERROR: MethodError: propertynames(::T, ::Bool) is ambiguous. Candidates:
propertynames(x, private::Bool) in Base at reflection.jl:1666
propertynames(::T, ::Integer) in Main at REPL[2]:1
关于generics - Julia 如何扩展 isless 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70316637/