generics - Julia 如何扩展 isless 函数

标签 generics julia

我是 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 中的函数添加一个方法。模块和两者 AbstractFloatAbstractString也在 Base 中定义模块。问题是添加这样的方法可能会破坏在这种情况下假定 isless 的其他代码。当通过 AbstractFloatAbstractString抛出错误。

你应该定义你的函数的方式是例如如下:

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/

相关文章:

julia - Julia 中复合类型的自定义显示

java - 通过传递泛型方法进行重构

C++ 保留指向模板对象的指针集合,所有指针都派生自非模板类

python - Julia 神经网络代码速度与 PyPy 相同

machine-learning - 使用 evaluate!() 时的 MLJ 预测类型确定性错误

date - 在 Julia 中是否有一种有效的方法可以将程序的执行暂停到第二天?

julia - 矢量化飞溅

java - 使用 Java 泛型的多个绑定(bind)类型定义接口(interface)

java - 为什么 <T> Matcher<T> 作为 Hamcrest instanceOf 方法的返回类型

java - 如何分配具有许多细节的 ArrayList