【问题标题】:Julia function with different parameter subtypes具有不同参数子类型的 Julia 函数
【发布时间】:2016-11-05 02:41:10
【问题描述】:

在 Julia 中,我可以定义一个接受 Type 的所有子类型的函数

function foo{T<:Type}(bar::T, arg::T) end

但这要求barargType 的同一子类型。是否有简写来定义一个函数,该函数接受 Type 的不同子类型 bararg?我知道我能做到

function foo{T<:Type, S<:Type}(bar::T, arg::S) end

但是对于一个有多个参数的函数,就变得相当繁琐了。

【问题讨论】:

  • 顺便提一下,如果bararg的类型不是参数化的,则不需要使用参数化方法。例如function foo{T&lt;:Integer}(bar::Vector{T}, arg::Number)
  • @GnimucK。我知道,但它们都是数组。

标签: function types julia


【解决方案1】:

T&lt;:Type 左侧使用的类型是抽象类型时,声明为T 类型的函数参数将接受属于该抽象的所有事物,包括事物属于从属(继承)抽象。

对于大多数目的,这些东西是具体类型的实现,类型的实例化。一个具体类型可能有一个抽象类型作为它的超类型,而这个抽象类型可能有另一个更抽象的类型作为它的超类型,等等。 Any 是最超超类型,是抽象类型树的根。

在示例中

 function foo{T<:Type}(bar::T, arg::T) ... end

在每次调用 foo 时,T 恰好采用 Type 的子类型之一或保持 Type 本身。这就是为什么bararg 必须共享相同的特定类型才能匹配和调用此版本的foo。它解释了为什么下一个示例匹配并被调用

 function foo{T<:Type, U<:Type}(bar::T, arg::U) ... end

foobar 都是Type 的子类型但都是两种不同具体类型的实现(例如Int32Int64 共享抽象超类型Integer)。

对于使用您打算接受不同类型事物的参数,没有通用的简写;不同种类共享一个公共抽象类型是有用的信息,并且允许您定义调用foo 的第一种和第二种方法。这种管理算法规范的灵活方式通常可以简化实现。这就是 Julia 的多分派提供的一些优势。

在某些情况下,使用typealias 可以简化函数签名的编写。 typealias 可以很好地使用共享超类型的非重叠子类型集合来选择性地调度。

typealias FastInt Union{ Int32, Int64 }  # division is fast
typealias SlowInt Union{ Int8, Int128 }  # slightly slower

foo{T<:Integer}(a::T, b::T) ... end; # default/fallback 
foo{T<:FastInt}(a::T, b::T) ... end; # specialized for fast types
foo{T<:SlowInt}(a::T, b::T) ... end; # specialized for slow types

```

【讨论】:

  • 所以没有速记。伤心。我真的在写function foo{T&lt;:Type}(bar::AbstractArray{T}, arg::AbstractArray{T}) end。应该指定的。无论如何,谢谢!
【解决方案2】:

我会简单地写成这样

function foo(bar::MyType, arg::MyType)
    ...
end

在函数内部,如果需要具体类型,请使用typeof(bar)typeof(arg)。这些是常数,因此不会影响性能。

当然,我假设您的意思是 Type 是一些用户定义的类型,而不是内置的 Type 类型。

即使参数是数组,函数也不需要参数化地编写。完全没问题

function foo(bar::AbstractArray, arg::AbstractArray)
    ...
end

如果需要,在函数内部使用eltype(bar)eltype(arg)。但是,如果需要eltypes,我个人会使用参数形式。

【讨论】:

  • 我应该更具体一些,但我真的在写function foo{T&lt;:Type}(bar::AbstractArray{T}, arg::AbstractArray{T}) end
  • @Mauricio:是的,那我更喜欢参数化方法。
  • 好吧,我认为重点是避免功能检查。此外,我不确定如何在不指定类型的情况下指定维度,还是我遗漏了一些明显的东西?
  • 您可以使用typealias 指定维度。
  • 但正如我在回答中所说,在这些情况下,我更喜欢参数形式 {T&lt;:Type,U&lt;:Type}
猜你喜欢
  • 2020-01-23
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
  • 1970-01-01
  • 2023-03-09
  • 2017-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多