nashcft's blog

時々何か書く。

Seven More Languages in Seven Weeks の Juliaパートを読む: Day 1

Julia入門の為に買ったSeven more Languages in Seven Weeksを読み始めたので1日分ずつブログに書いて記録する事にした。

この本で扱われているJuliaのバージョンは0.3.0だけど自分の環境が0.4.0-devなので、その辺の差異は夜道さんのJulia本やブログ記事、公式docで調べつつ進めている。

Day 1: Resistance Is Futile

インストールの話などもそこそこに、まずはJuliaの型の紹介から始まる。
延々とtypeof()に値を突っ込んでみていく。気になったのでtypeof()に型名を入れるとDataTypeと出力された。
型紹介の最後にDictが出てきたがこれは0.3.xと0.4.xでは定義方法が異なる。

# v0.3
# {}で括ると型の束縛のないDictができる。
julia> {:a => 12}
Dict{Any,Any} with 1 entry:
  :a => 12

# []で括ると値からの型推論で型が固定される。
julia> [:a => 12]
Dict{Symbol,Int64} with 1 entry:
  :a => 12

# 前に(KeyType => ValueType)と書く事で型を指定できる。
julia> (ASCIIString => Float32)["a" => 1.2]
Dict{ASCIIString,Float32} with 1 entry:
  "a" => 1.2f0
# v0.4
# Dict(key => value, ...)と定義する。この定義方法だと型推論される。
julia> Dict(:a => 12)
Dict{Symbol,Int64} with 1 entry:
  :a => 12

# 型を明示的に指定する際はDict{KeyType, ValueType}(key => value, ...)
julia> Dict{Any, Any}(:a => 12)
Dict{Any,Any} with 1 entry:
  :a => 12

次は演算子の紹介。除算関係には関数もある。この辺について夜道さんのJulia本に挙動の違いが書かれている。/を使うとInt同士の除算でも返り値がFloatになるが、div()を使うと返り値は整数値になる。div()の引数にFloatを入れると、Float型の整数(1.0とか)が返却される。
後はbit表現する為のbits()とか、bit演算子とか。

続いてDictionaryとSetの紹介。定義の方法はさっき書いた通り。値の取り出し方はdict[key]の他、存在しないkeyを指定した際のdefault値も指定するget(dict, key, default)もある。keyを全て取得するkeys()の返り値はKeyIteratorになる。collect()Iteratorから配列を作成する。

julia> numbers = Dict(:a => 1, :b => 2, :c => 3)
Dict{Symbol,Int64} with 3 entries:
  :b => 2
  :c => 3
  :a => 1

julia> numkey = keys(numbers)
KeyIterator for a Dict{Symbol,Int64} with 3 entries. Keys:
  :b
  :c
  :a

julia> numkey[2]
ERROR: MethodError: `getindex` has no method matching getindex(::KeyIterator{Dict{Symbol,Int64}}, ::Int64)
Closest candidates are:
  getindex(::(Any...,), ::Int64)
  getindex(::(Any...,), ::Real)
  getindex(::FloatRange{T}, ::Integer)
  ...

julia> collect(numkey)[2]
:c

in演算子と関数とがあるDictionaryに対してin()を用いるときは第一引数がkeyとvalueのpairでなければならない。
Setにはunion(), intersection(), setdiff(), issubset()等の関数が備えられている。

Array。indexが1スタートなのが違和感ある。基本的に1つのArrayに複数の型の要素を入れられる。型指定するときはType[]と書く。zeros(), ones(),fill()といった初期化用の関数がある。あとはindex指定にendとかsliceがある。 sliceを使って再代入すると指定範囲全てに変更が適用される。 次元まわりは以下のような感じ。

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

julia> [1 2 3]
1x3 Array{Int64,2}:
 1  2  3

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

julia> [1 2 3; 4 5 6; 7 8 9]
3x3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

コンマでなくてセミコロンでもいいみたい。線形代数関係の演算をする為の関数も色々ある。eye()でidentity matrixを定義できたり、.*で要素ごとの乗算ができたり、Arrayの後に'をつけるとtransposeができたり。

Day 1の解説部分はこれでおしまい。この後に練習問題があるので解いてどこかに放り投げる予定。