Syntactic Goodies Julia

Dans cet article, je veux parler des brioches de syntaxe savoureuses et utiles Julia, qui devraient adoucir la part amère du programmeur.


Aller!


image


Les opérateurs Infix sont des fonctions ordinaires.


, +, -, <, ==, in (&& || , .. - "" ), ( ). , .


, :


struct SetOfTwo{T}
     a::T
     b::T
     function SetOfTwo(a::A, b::B) where {A,B}
        if a != b
            T = promote_type(A, B)
            return new{T}(a, b)
        else
            throw(ArgumentError("Set elements must be distinct"))
        end
    end
end

:


Base.in(x, s::SetOfTwo) = x == s.a || x == s.b

Base.:(==)(s1::SetOfTwo, s2::SetOfTwo) = (s1.a in s2) && (s1.b in s2)

:


Base.:(==)(s1::SetOfTwo, s2::AbstractSet) = length(s2) == 2 && s1.a in s2 && s1.b in s2
Base.:(==)(s1::AbstractSet, s2::SetOfTwo) = s2 == s1

, , . , , :


julia> ⇒(a::Bool, b::Bool) = b || !a
⇒ (generic function with 1 method)

julia> struct  end

julia>  = ()

julia> 2 * 2 == 4 ⇒  isa 
true

!


: fn, , !fn — , .


julia> filter(!ismissing, [1, missing, missing, 3, 5, 8, missing])
4-element Array{Union{Missing, Int64},1}:
 1
 3
 5
 8


Julia - for , . for — for x in collection ... end. , . , iterate(collection[, state]), for :


for x in collection
    ...
end
    ⇓
let iter = iterate(collection)
while !isnothing(iter)
    x, state = iter
    ...
    iter = iterate(collection, state)
end

, iterate nothing, .


, , foreach ( ), collect ( ), in ( ) . , , . , , — , .


, , Base.Iterators . — , , , . , , .


Comprehensions


julia> [x for x in 1:3] # 
3-element Array{Int64,1}:
  1
  2
  3

julia> Float64[x^3 for x in 1:10 if iseven(x)] #   
5-element Array{Float64,1}:
    8.0
   64.0
  216.0
  512.0
 1000.0

julia> Dict(string(s) => length(s) for s in split("     ")) # 
Dict{String,Int64} with 6 entries:
  ""         => 1
  ""     => 5
  ""      => 4
  ""         => 1
  "" => 9
  ""       => 3

-, Python. Python , comprehension' , .


comprehension' — , :


julia> @btime sum([x for x in 1:10])
  38.467 ns (1 allocation: 160 bytes)
55

julia> @btime sum(x for x in 1:10)
  1.552 ns (0 allocations: 0 bytes)
55

, , , coll x for x in coll, — iterate. .



... :


julia> min(1, 2, 3)
1

julia> min([1, 2, 3])
ERROR: MethodError: no method matching min(::Array{Int64,1})
  ...

julia> min([1, 2, 3]...)
1

, . . — , :


julia> range_settings = Dict(:stop => 10, :step => 3)
Dict{Symbol,Int64} with 2 entries:
  :stop => 10
  :step => 3

julia> range(1, range_settings...)
ERROR: MethodError: no method matching range(::Int64, ::Pair{Symbol,Int64}, ::Pair{Symbol,Int64})
  ...

— , , . — , . , -:


julia> range_settings = Dict(:stop => 10, :step => 3)
Dict{Symbol,Int64} with 2 entries:
  :stop => 10
  :step => 3

julia> range(1; range_settings...)
1:3:10

julia> range_settings = [:stop => 10, :step => 3]
2-element Array{Pair{Symbol,Int64},1}:
 :stop => 10
 :step => 3

julia> range(1; range_settings...)
1:3:10

julia> range_settings = Set(range_settings)
Set{Pair{Symbol,Int64}} with 2 elements:
  :step => 3
  :stop => 10

julia> range(1; range_settings...)
1:3:10

— . , , , .


julia> range_settings = (stop = 10, step = 3)
(stop = 10, step = 3)

julia> range(1; range_settings...)
1:3:10


— , — , , . :


#  
function crossproduct1(p1::NTuple{3, Real}, p2::NTuple{3, Real})
    return p1[2]*p2[3] - p1[3]*p2[2], p1[3]*p2[1] - p1[1]*p2[3], p1[1]*p2[2] - p1[2]*p2[1]
end

#  
function crossproduct2((x1, y1, z1)::NTuple{3, Real}, (x2, y2, z2)::NTuple{3, Real})
    return y1 * z2 - y2 * z1, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2
end

Broadcast


broadcasted-, , (loop fusion), ..


- ( / , / , , ) . , broadcast , , . — , "" , . , . "" broadcast(f, collection), , broadcast collection , .


, broadcast , . , , , .


julia> parse.(Int, ("3", "14", "15")).^(3, 2, 1)
(27, 196, 15)

julia> (x -> x / 5).(parse.(Float64, ["92", "65", "36"]))
3-element Array{Float64,1}:
 18.4
 13.0
  7.2

julia> parse.(Int, ("3", "14", "15")).^(3, 2, 1) .+ (x -> x / 5).(parse.(Float64, ["92", "65", "36"]))
3-element Array{Float64,1}:
  45.4
 209.0
  22.2

do


: do- , .


foo(args...) do x
    do_something
end


foo(x -> do_something, args...)

?


-, - map accumulate:


# 
map(x -> begin
            a, b, c = x[1], x[2], x[3]
            return a - (b + c) / 2, b - (a + c) / 2, c - (a + b) / 2
         end,
    [A, B, C])

# 
map([A, B, C]) do x
    a, b, c = x[1], x[2], x[3]
    return a - (b + c) / 2, b - (a + c) / 2, c - (a + b) / 2
end

-, with ... as ... Python. , open , :


open(f -> println(readline(f)), "myfile.txt", "r")

# 
open("myfile.txt", "r") do io
    firstline = readline(io)
    println(firstline)
end

, open , , , , :


function open(f::Function, args...)
    io = open(args...)
    try
        f(io)
    finally
        close(io)
    end
end

, — , do-. , , — , .


, , , .


All Articles