在Julia中使用N重参数类型与使用抽象向量

在Julia中使用N重参数类型与使用抽象向量,julia,Julia,我目前正在开发一个支持二进制操作的解析器。表示二进制操作的思想是使用这种结构 struct Binary{T <: BinaryKind} <: Operation xs::Vector{Union{Operation, Atom}} end 但由于我可以使用嵌套的二进制操作,我相信在某些情况下,我最终可能会得到非常长的类型定义,这可能比只使用抽象类型更糟糕。有什么方法可以改进吗?我认为(评论太长了,所以我给出了答案),在这种情况下,最好是类型不稳定。请注意,这正是Juli

我目前正在开发一个支持二进制操作的解析器。表示二进制操作的思想是使用这种结构

struct Binary{T <: BinaryKind} <: Operation
    xs::Vector{Union{Operation, Atom}}
end
但由于我可以使用嵌套的二进制操作,我相信在某些情况下,我最终可能会得到非常长的类型定义,这可能比只使用抽象类型更糟糕。有什么方法可以改进吗?

我认为(评论太长了,所以我给出了答案),在这种情况下,最好是类型不稳定。请注意,这正是Julia自己所做的:

julia> x = :(1+2*(3+4))
:(1 + 2 * (3 + 4))

julia> dump(x)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Int64 1
    3: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol *
        2: Int64 2
        3: Expr
          head: Symbol call
          args: Array{Any}((3,))
            1: Symbol +
            2: Int64 3
            3: Int64 4
当然,朱丽亚有一个更丰富的语法,但即使在简单的情况下,也要考虑下面的内容。如果您只编译一次代码的某些部分,然后多次(以这种或其他形式)运行它,就可以获得类型稳定性的好处

现在我假设你写的东西实际上只会被评估一次。如果您使表达式的类型完全稳定,则每次都必须付款(假设表达式发生更改):

  • 编译它的成本(昂贵)
  • 运行它的成本(相对便宜)
  • 如果您的代码类型不稳定,您只需支付一次编译成本。确实,运行它会稍微慢一点,但总的来说,这样做可能会更好

    另一方面,如果希望只定义一次表达式,然后运行多次,那么更好的方法可能是使用元编程:

  • 只处理表达式一次,并生成将对表达式求值的Julia代码
  • 然后Julia将编译生成的代码一次
  • 在完成步骤1和步骤2后,您可以获得执行它的最大性能

  • 对您的问题的一半衡量标准是使用以下数据结构:

    struct Binary{T <: BinaryKind, S} <: Operation
        xs::Vector{S}
    end
    

    <代码>结构二进制{t考虑你是否真的需要限制参数<代码> d>代码>。你可以使用<代码>结构二进制{T该限制没有特定用途,但由于它始终是一个元组,因此我最终会使用长嵌套类型。避免指定元组内容对类型推断更好吗?那么,您不能不指定它,然后完全停止键入嵌套元组吗?我认为这对键入没有任何影响感谢您的回答。对于一些操作,我需要改变表达式,因此最好的解决办法可能是使用您建议的半度量。这是说,在一些情况下,我没有改变表达式,也许使用基于元编程的方法会更好。我可能会考虑。一种保持数据结构与我现在的数据结构相似的方法,但在类型稳定性更好时使用Julia的表达式语法。
    struct Binary{T <: BinaryKind, S} <: Operation
        xs::Vector{S}
    end