Is Julia lazy?

So, it never really occurred to me that elegance was the enemy of true mathematics :upside_down_face: But anyway, I just wanted to show a simpler example:

struct Z{P} <: Integer
    x::Int
    Z{P}(n::Integer) where {P} = new{P}(mod(n, P))
end

Base.promote_rule(::Type{<:Number}, ::Type{Z{P}}) where {P} = Z{P}
Base.show(io::IO, z::Z) = show(io, z.x)

Base.:+(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x + b.x)
Base.:-(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x - b.x)
Base.:-(a::Z{P}) where {P} = Z{P}(-a.x)
Base.:*(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x * b.x)
Base.div(a::Z{P}, b::Z{P}) where {P} = Z{P}(a.x ÷ b.x)  # I don't think this is needed, really

Now you can

jl> z = zeros(Z{7}, 3, 3)
3×3 Matrix{Z{7}}:
 0  0  0
 0  0  0
 0  0  0

jl> one(z)
3×3 Matrix{Z{7}}:
 1  0  0
 0  1  0
 0  0  1

jl> z = Z{11}.(rand(0:10, 3, 3))
3×3 Matrix{Z{11}}:
  3  3   4
  3  4   5
 10  4  10

jl> z.^2 .+ 1
3×3 Matrix{Z{11}}:
 10  10  6
 10   6  4
  2   6  2

jl> maximum(z.^2 .+ 1)
10

jl> (2 + 3im) * Z{11}(2)
4 + 6im

# etc.

I think comparison and random sampling is really neat, but whatever.

Base.:<(a::Z{P}, b::Z{P}) where {P} = (a.x < b.x)
Base.:<=(a::Z{P}, b::Z{P}) where {P} = (a.x <= b.x)
function Random.rand(rng::AbstractRNG, ::Random.SamplerType{Z{P}}) where {P}
    return Z{P}(rand(rng, 0:P-1))
end

Anyway, if you are teaching this to students, you shouldn’t drag macros into it, and for all that is holy, don’t use global(!)

13 Likes