关于Base.:+

初学Julia
练习的时候尝试重载+运算符,
查了一下文档,发现正确的写法是:
import Base
Base.:+(a, b) = Point(a.x + b.x, a.y + b.y)

请问该如何理解这里的Base.:+ ?
除了操作符函数之外,在什么场合下还会用到“.:”的这种写法?

不是 .: ,而是 :+ .如果你重载 println 的话,就是 Base.println,重载 * 就是 Base.:* 因为 Base.+ 会被解析成 Base .+ 就是一个叫 Base 的变量.(我猜的) 另外可以看Juliacon 2021 讲 元编程(Meta Programming) 的那个视频,讲得挺好的

1 个赞
julia> +(x, y) = x*y
+ (generic function with 1 method) # 这里重新定义了一个新的函数,而不是在原有的 Base 里作运算符重载

julia> +(2, 3)
6

正如 @Sukanka 所说 Base.+ 在语法解析上有歧义,所以这里需要用 :+ 来表示它

1 个赞

:+ 代表一个 Symbol

julia> :+
:+

julia> :+ |> typeof
Symbol
1 个赞

跳到元编程一章仔细读了一下,恍然大悟~

读元编程一章时发现还有这种写法:

julia> : ( : )
: ( : )

julia> : ( : : )
: ( : : )

有意思~

请问要是想重载==的话应该怎么写呢 ?Base.:==好像不大对

Base.:(==)

1 个赞

试着定义了一个向量的module,感觉写得很别扭,请问julia的程序写出来是下面这个味儿吗?


(其中13-15行是报错的 )

  • Julia 里函数名称小写 some_function_name
  • Length 是一个有歧义的名称 (Julia 里有 Base.length)
  • 简单的情形下构造函数可以不用写
  • 多重派发分在多个层次上做,这里完全不需要要求 lhsrhs 是同一类型
  • 复用现有的基础设施(例如 Vec2 完全可以使用 StaticArrays里的 SVector{2, T} 来取代)
struct Vec2{T<:Real}
    x::T
    y::T
end
Vec2(x::Real, y::Real) = Vec2(promote(x, y)...)

for op in (:+, :-, :*, :/)
    @eval Base.$op(lhs::Vec2, rhs::Vec2) = Vec2($op(lhs.x, rhs.x), $op(lhs.y, rhs.y))
end
Base.zero(v::T) where T<:Vec2 = T(0, 0)
Base.show(io::IO, v::Vec2) = println(io, v.x, "\t", v.y)

radius(v::Vec2) = sqrt(v.x^2 + v.y^2)
dot(lhs::Vec2, rhs::Vec2) = lhs.x * rhs.x + lhs.y * rhs.y
function normalize(v::T) where T<:Vec2
    r = radius(v)
    return == 0 ? zero(T) : T(v.x/r, v.y/r)
end
1 个赞

感谢感谢~
我晚上学习一下^_^

研究了一下SVector然后继续修改程序
这样写是不是更像Julia的代码?
请问还有没有什么不够Julia的地方?

module Vec2
    using LinearAlgebra
    using StaticArrays

    function Init(x::T, y::T) where {T}
        SVector{2, T}(x, y)
    end

    X(v::SVector{2, T}) where {T} = v[1]
    Y(v::SVector{2, T}) where {T} = v[2]

    Dot(v1::SVector{2, T}, v2::SVector{2, T}) where {T} = dot(v1, v2)
    Normalize(v::SVector{2, T}) where {T} = normalize(v)
    Length(v::SVector{2, T}) where {T} = norm(v)

    function Proj(v::SVector{2, T}, p::SVector{2, T}) where {T}
        vp = normalize(p)
        dot(v, vp)
    end
end
  1. 为什么一定要引入一堆不必要的函数封装呢?
  2. 不需要 T 类型的时候就可以不去写它。
using LinearAlgebra
using StaticArrays

const Point{T} = SVector{2, T}
project(v::Point, p::Point) = dot(v, normalize(p))
2 个赞

有点找到感觉了~
感谢!!