【问题标题】:Constructing types with related fields in Julia在 Julia 中构造具有相关字段的类型
【发布时间】:2016-12-08 19:09:20
【问题描述】:

我想创建一个 Julia 类型,其中包含彼此之间具有固定关系的字段。为了说明,考虑一个 Point 类型,它表示二维中的一个点,并且它的字段表示它的笛卡尔 (x,y) 和极坐标 (r,theta) 坐标。这些字段必须通过 r*cos(theta)=x 和 r*sin(theta)=y 关联,并且您应该能够通过指定任意一组坐标来构造点。问题是:为这种类型创建构造函数的好方法是什么?

【问题讨论】:

  • 以一种方式存储它并具有以另一种形式给出坐标的函数怎么样?
  • @ChrisRackauckas 通常(对于比我给出的 Point 示例更复杂的类型),字段之间的关系可能很复杂且计算成本很高。最好只计算一次并将其与对象永久关联。
  • 这不是那么简单,因为也许内存是更大的需求,所以一如既往,这取决于应用程序。如果您需要,那么您可以编写这些函数并在构造函数中使用它们。这有什么问题?

标签: types constructor julia


【解决方案1】:

如果您乐于引入“子”类型,则可以执行以下操作:

type Cartesian
  x::Float64;  y::Float64
end

type Polar
  r::Float64;  t::Float64
end

type Point
  x::Float64;  y::Float64
  r::Float64;  t::Float64
end

# secondary external constructors
Point(c::Cartesian) = Point(c.x, c.y, sqrt(c.x^2+c.y^2), atan2(c.y, c.x))
Point(p::Polar) = Point(p.r * cos(p.t), p.r * sin(p.t), p.r, p.t)
Point(x::Float64, y::Float64) = Point(Cartesian(x,y))   # ... etc

另外,关于 Chris 的评论,一种两全其美的方法是创建一个闭包生成函数,而不是一个简单的转换函数,这样一旦它被初始化,它就会保留状态和可用于免费将转换返回到极地。

【讨论】:

    【解决方案2】:

    这是一个可能的实现:

    abstract CoordSys
    abstract Cartesian <: CoordSys
    abstract Polar <: CoordSys
    
    transform(r, theta, ::Type{Polar}) = r*cos(theta), r*sin(theta)
    transform(x, y, ::Type{Cartesian}) = sqrt(x^2+y^2), atan2(y, x)
    
    immutable Point{T<:AbstractFloat}
        x::T
        y::T
        r::T
        theta::T
        function Point(x, y, r, theta)
            x_ctrl, y_ctrl = transform(r, theta, Polar)
            if isapprox(x_ctrl, x, atol = 1e-15) && isapprox(y_ctrl, y, atol = 1e-15)
                new(x, y, r, theta)
            else
                error("Coordinates are inconsistent")
            end
         end
     end
    
     # These constructors take the coordinate system as an additional argument
     Point{T<:AbstractFloat}(x::T, y::T, C::Type{Cartesian}) = Point{T}(x, y, transform(x,y,C)...)
     Point{T<:AbstractFloat}(r::T, theta::T, C::Type{Polar}) = Point{T}(transform(r,theta,C)..., r, theta)
    
     # Convenience methods
     Point{C<:CoordSys}(x::Real, y::Real, ::Type{C}) = Point(promote(float(x), float(y))..., C)
     Point(x, y) = Point(x, y, Cartesian)
    

    它使用内部构造函数在构造时强制执行关系,并在构造后使用immutable 类型来强制执行它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-14
      • 2019-02-19
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多