Julia特有の構文メモ2

ライブラリ

Juliaの関数は大きく3つに分けられる.

  • コアベースの関数
  • 標準ライブラリの関数
  • 外部ライブラリの関数

コアベースの関数

Core.関数

Core.ifelse 判定文が真なら1つ目、偽なら2つ目の引数を返す.

julia> Core.ifelse('a' < 'A', 'a', 'A')
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)

julia> Core.ifelse(10/3==10÷3, "same", "not same")
"not same"

#juliaのif判定はboolean型しか受け付けない.
julia> Core.ifelse(1, "one", "not one")
ERROR: TypeError: non-boolean (Int64) used in boolean context
Stacktrace:
 [1] top-level scope at REPL[4]:1

Core.applicable 引数が関数に適用可能か判定する.

julia> myfunc(a::Int64,b::Int64)=a*b
myfunc (generic function with 1 method)

#引数が一つだけでもダメ
julia> applicable(myfunc,2)
false

#片方がFloatでもダメ
julia> applicable(myfunc,2,2.5)
false

#2つが両方IntならOK
julia> applicable(myfunc,2,2)
true

Core.tuple タプルを作成する(関数がTupleではなくtuple).

julia> stationery=tuple("Pencil","Eraser","Ruler")
("Pencil", "Eraser", "Ruler")

julia> typeof(stationery)
Tuple{String,String,String}

参照渡しについて. 変数の代入は=で普通に値を渡すだけ. bの値を更新してもaは影響を受けない. 値が格納される参照先(アドレス)が別々だから.

julia> a = 2
2

julia> b = a
2

julia> b = 3
3

julia> a
2

一方でコレクションは参照渡しなので、 代入した後で更新すると、元のも更新される.

julia> arr_a = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> arr_b = arr_a
3-element Array{Int64,1}:
 1
 2
 3

julia> arr_b[2]=20
20

julia> arr_a
3-element Array{Int64,1}:
  1
 20
  3

Base.関数

Base.copy 浅いコピーcopyと深いコピーdeepcopyがある. 参照渡しでないコピーなので、値を更新しても互いに影響しない.

julia> ary_a = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> ary_cp = copy(ary_a)
3-element Array{Int64,1}:
 1
 2
 3
julia> ary_dpcp = deepcopy(ary_a)
3-element Array{Int64,1}:
 1
 2
 3

julia> ary_a[2] = 20
20

julia> ary_cp
3-element Array{Int64,1}:
 1
 2
 3

julia> ary_dpcp
3-element Array{Int64,1}:
 1
 2
 3

Base.pointer 配列や文字列のアドレスを出力する.

julia> pointer(ary_a)
Ptr{Int64} @0x0000000109e47a10

要素が配列になっている深い配列を考える. 浅いコピーではary_aの更新に伴って値が変わっている.

julia> ary_a = [[1,2,3],[4,5,6]]
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [4, 5, 6]

julia> ary_shallow = copy(ary_a)
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [4, 5, 6]

julia> ary_deep = deepcopy(ary_a)
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [4, 5, 6]

julia> ary_a[2][2] = 50
50

julia> ary_shallow
2-element Array{Array{Int64,1},1}:
 [1, 2, 3] 
 [4, 50, 6]

julia> ary_deep
2-element Array{Array{Int64,1},1}:
 [1, 2, 3]
 [4, 5, 6]

アドレスを見てみると、外枠は違うように見えるが、

julia> pointer(ary_a)
Ptr{Array{Int64,1}} @0x000000010a56d7f0

julia> pointer(ary_shallow)
Ptr{Array{Int64,1}} @0x0000000109b7b290

julia> pointer(ary_deep)
Ptr{Array{Int64,1}} @0x000000010a0a59d0

その要素は、浅いコピーでは元配列と同じ場所に格納されているらしい.

julia> pointer(ary_a[2])
Ptr{Int64} @0x00000001099c5a90

julia> pointer(ary_shallow[2])
Ptr{Int64} @0x00000001099c5a90

julia> pointer(ary_deep[2])
Ptr{Int64} @0x00000001099a2f90

Base.Core..の前を省略できるが、関数によって出来るものと出来ないものがある.

標準ライブラリの関数

Juliaインストール時からすでに用意されている関数. 使う際にはusingで関数名を宣言する必要がある.

Dates.関数

julia> Dates.now()
ERROR: UndefVarError: Dates not defined
Stacktrace:
 [1] top-level scope at REPL[43]:1

julia> using Dates

julia> Dates.now()
2019-10-25T20:51:38.306

Dates.を省略してもいい.

julia> now()
2019-10-25T20:54:06.016

now()関数はDateTime型、Data()関数はDate型を返す. year()関数は年を取得する. dayofweek()関数は曜日の値、dayname()関数は曜日の名前を返す.

julia> typeof(now())
DateTime

julia> Date(now())
2019-10-25

julia> year(now())
2019

julia> year(Date("2019-10-25"))
2019

julia> dayofweek(now())
5

julia> dayname(now())
"Friday"

Day()は日、Hour()は時間を取得する. それぞれDay型、Hour型.

julia> Day(now())
25 days

julia> Hour(now())
21 hours

足したり引いたり、計算もできる.

julia> Day(now() + Hour(3))
26 days

julia> Date("2019-10-25") + Day(1000)
2022-07-21

型が違う場合

#`==`は計算結果が同じならOK.
julia> Hour(1) == Minute(45) + Minute(15)
true

#`===`は型が同じでないとダメ.
julia> Hour(1) === Minute(45) + Minute(15)
false

外部ライブラリの関数

JSONを例に.

using JSON

#JSON形式にシリアライズするための辞書を用意する.
julia> stationery=Dict("Pencil"=>80,"Eraser"=>50,"Ruler"=>100)
Dict{String,Int64} with 3 entries:
  "Ruler"  => 100
  "Eraser" => 50
  "Pencil" => 80

julia> JSON.print(stationery)
{"Ruler":100,"Eraser":50,"Pencil":80}

#インデントの指定.4は4文字分ということ.
julia> JSON.print(stationery,4)
{
    "Ruler": 100,
    "Eraser": 50,
    "Pencil": 80
}

JSON形式にシリアライズした文字列の取得.

julia> stationery_json = JSON.json(stationery)
"{\"Ruler\":100,\"Eraser\":50,\"Pencil\":80}"

JSON形式のデータをパース.

julia> stationery_parse = JSON.parse(stationery_json)
Dict{String,Any} with 3 entries:
  "Ruler"  => 100
  "Eraser" => 50
  "Pencil" => 80

julia> println(stationery_parse)
Dict{String,Any}("Ruler" => 100,"Eraser" => 50,"Pencil" => 80)

#元々の辞書.
julia> println(stationery)
Dict("Ruler" => 100,"Eraser" => 50,"Pencil" => 80)