Julia 手册和定义中缀运算符

问题描述 投票:0回答:1

以下代码来自 Julia 手册。我的问题如下。

julia> struct OurRational{T<:Integer} <: Real
           num::T
           den::T
           function OurRational{T}(num::T, den::T) where T<:Integer
               if num == 0 && den == 0
                    error("invalid rational: 0//0")
               end
               num = flipsign(num, den)
               den = flipsign(den, den)
               g = gcd(num, den)
               num = div(num, g)
               den = div(den, g)
               new(num, den)
           end
       end

julia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)
OurRational

julia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)
OurRational

julia> OurRational(n::Integer) = OurRational(n,one(n))
OurRational

julia> ⊘(n::Integer, d::Integer) = OurRational(n,d)
⊘ (generic function with 1 method)

julia> ⊘(x::OurRational, y::Integer) = x.num ⊘ (x.den*y)
⊘ (generic function with 2 methods)

julia> ⊘(x::Integer, y::OurRational) = (x*y.den) ⊘ y.num
⊘ (generic function with 3 methods)

julia> ⊘(x::Complex, y::Real) = complex(real(x) ⊘ y, imag(x) ⊘ y)
⊘ (generic function with 4 methods)

julia> ⊘(x::Real, y::Complex) = (x*y') ⊘ real(y*y')
⊘ (generic function with 5 methods)

julia> function ⊘(x::Complex, y::Complex)
           xy = x*y'
           yy = real(y*y')
           complex(real(xy) ⊘ yy, imag(xy) ⊘ yy)
       end
⊘ (generic function with 6 methods)

作为这些定义的结果,手册给出了这个例子

julia> z = (1+2im)⊘(1-2im);
Julia> typeof(z)
Complex{OurRational{Int64}}

这很好用......除非你省略“;”

julia> z = (1+2im)⊘(1-2im)
OurRational{Int64}(-3, 5)Error showing value of type Complex{OurRational{Int64}}:
ERROR: promotion of types OurRational{Int64} and Int64 failed to change any arguments
Stacktrace:
  [1] error(::String, ::String, ::String)
    @ Base ./error.jl:44
  [2] sametype_error(input::Tuple{OurRational{Int64}, Int64})
    @ Base ./promotion.jl:417
  [3] not_sametype(x::Tuple{OurRational{Int64}, Int64}, y::Tuple{OurRational{Int64}, Int64})
    @ Base ./promotion.jl:411
  [4] promote
    @ ./promotion.jl:394 [inlined]
  [5] <(x::OurRational{Int64}, y::Int64)
    @ Base ./promotion.jl:462
  [6] signbit(x::OurRational{Int64})

我不知道为什么。如果您使用内置的 Rational 运算符

julia> z = (1+2im)//(1-2im)

没问题。

有什么想法吗?

julia infix-operator
1个回答
0
投票

根本问题是

OurRational{Int}
Int
是不兼容的类型:
Int
无法转换为
OurRational{Int}
。检查堆栈跟踪将显示以下内容:

OurRational{Int64}(-3, 5)ERROR: promotion of types OurRational{Int64} and Int64 failed to change any arguments
Stacktrace:
  [1] error(::String, ::String, ::String)
    @ Base ./error.jl:44
  [2] sametype_error(input::Tuple{OurRational{Int64}, Int64})
    @ Base ./promotion.jl:417
  [3] not_sametype(x::Tuple{OurRational{Int64}, Int64}, y::Tuple{OurRational{Int64}, Int64})
    @ Base ./promotion.jl:411
  [4] promote  <-- issue here ********
    @ ./promotion.jl:394 [inlined]
  [5] <(x::OurRational{Int64}, y::Int64)
    @ Base ./promotion.jl:462
  [6] signbit(x::OurRational{Int64})
    @ Base ./number.jl:137
  [7] show(io::IOContext{Base.TTY}, z::Complex{OurRational{Int64}})
    @ Base ./complex.jl:201
  [8] show(io::IOContext{Base.TTY}, ::MIME{Symbol("text/plain")}, x::Complex{OurRational{Int64}})
    @ Base.Multimedia ./multimedia.jl:47
<snip>

要解决此问题,请定义:

Base.promote_rule(::Type{OurRational{T}}, ::Type{S}) where {T,S} =
    OurRational{promote_type(T, S)}

现在……

OurRational{Int64}(-3, 5)ERROR: MethodError: no method matching OurRational{Int64}(::Int64)

Closest candidates are:
  OurRational{T}(::T, ::T) where T<:Integer
   @ Main ~/Offline-Documents/Scratchpad/f.jl:5
  (::Type{T})(::T) where T<:Number
   @ Core boot.jl:792
  (::Type{T})(::Complex) where T<:Real
   @ Base complex.jl:44
  ...

Stacktrace:
<snip>

好吧,让我们定义一下:

OurRational{T}(n::T) where {T<:Integer} = OurRational(n)

不完全在那里......

OurRational{Int64}(-3, 5)ERROR: < not defined for OurRational{Int64}
Stacktrace:
<snip>

再试一次:

# actual implementation left as exercise
Base.:(<)(x::OurRational{S}, y::OurRational{T}) where {S,T} = x.num//x.den < y.num//y.den

成功!

julia> z = (1 + 2im) ⊘ (1 - 2im)
OurRational{Int64}(-3, 5) + OurRational{Int64}(4, 5)*im
© www.soinside.com 2019 - 2024. All rights reserved.