Juliaをさわってみた
Juliaのドキュメントを読みながら、インストールして、いくつかの機能を調べて試してみました。
インストール
brewでインストール
Macでbrewを使っていて、brew cask
を使える状態になっていれば、brew cask install
でインストールできます。
dockerイメージを使う
dockerのイメージも提供されているので、それを使う事もできます。
Docker Hubのリポジトリがあるので、docker run
で起動イメージにjulia
を指定すると自動でpullしてきて、REPLが立ち上がります。
$ docker run -it --rm --name julia julia
Unable to find image 'julia:latest' locally
latest: Pulling from library/julia
8ec398bc0356: Pull complete
e59afaf5b9ab: Pull complete
a8ff93c6b967: Pull complete
Digest: sha256:3f007403ad08637b46523a8025b2f69ff1515d96b411ab0b7abe29ca200e43a9
Status: Downloaded newer image for julia:latest
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.3.1 (2019-12-30)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia>
Juliaの実行方法
Juliaの実行方法には大きく2つあります。 REPL上で実行する場合と、juliaのソースコードをjuliaコマンドに渡す方法です。
REPLで実行する
REPLとは、対話形式でJuliaの式を評価し、結果をみることができるツールです。 Shellのように、プロンプトが表示され、Juliaの式を入力しEnterを入力すると、その式が評価され結果が表示されます。
julia> print("Hello, Julia")
Hello, Julia
ちなみに、REPLは、read-eaval-print loop
(Read(読み込む)、Eval(評価する)、Print(出力する)、Loop(繰り返す))の頭文字をとったものです。
juliaコマンドで実行する
$ echo 'print("Hello, julia!\n")' > hello.jl
$ julia hello.jl
Hello, julia!
変数
Juliaの変数は、値に束縛した名前です。
以下は、10
をx
という名前に束縛します。
julia> x = 10
10
変数名には、Unicodeを使用する事もできます。
julia> ハロー = "わーるど"
"わーるど"
julia> ハロー
"わーるど"
JuliaのREPLでは、バックスラッシュをつけたLaTex
の数式記号を使うことで、α̂₂
のような文字も入力することができます。
REPLで\alpha
+ <TAB>
+ \hat
+ <TAB>
+ \_2
+ <TAB>
を入力すると、 α̂₂
に変換されます。
julia> α̂₂ = 100
100
非推奨とされていますが、Juliaでは必要があれば、組み込み定数や関数を再定義することができます。 ただし、再定義するには、対象の定数や関数が一度も評価されていない必要があります。
julia> pi = 3
3
julia> pi
3
JuliaのREPLを再起動し、先に評価した場合、上書き時にエラーになります。
julia> pi
π = 3.1415926535897...
julia> pi = 3.14
ERROR: cannot assign a value to variable MathConstants.pi from module Main
型
Juliaの型は以下のようなものがあります。 整数型と不動小数点数型は、型名の後に型のビット数を指定して表現されます。
- Boolean型
- Bool
- 整数型
- Int8
- Int16
- Int32
- Int64
- Int128
- UInt8
- UInt16
- UInt32
- UInt64
- UInt128
- 不動小数点数型
- Float16
- Float32
- Float64
- 文字
- Char
- 文字列
- String
- SubString
Boolean
Bool
型は、trueまたは、falseを持つことができます。内部的には8bitの整数で表現されており、true(1)
、false(0)
になります。
julia> true == 1
true
julia> false == 0
true
整数型・不動小数点数型
Juliaには、整数型と不動小数点数型があり、typeofを評価するとそれぞれInt
とFloat
が返ってきます。
julia> typeof(100)
Int64
julia> typeof(100.0)
Float64
typemin
とtypemax
関数で型が取りうる最小と最大の値を取得できます。
julia> (typemin(Int8), typemax(Int8))
(-128, 127)
文字・文字列
文字列は、文字の並びです。英数字や記号などは、0から127までの整数値にマッピングされたASCIIを使うことができ、日本語などはUTF-8エンコーディングされたユニコードを使えます。
文字は'
で、文字列は"
で括られたものになります。
文字列は文字の並びなので、インデックスを指定して特定の文字を取得することができます。
文字列のインデックスの単位は1byteで、1から始まり、インデックスを1進めると1byte先の値が参照されます。
日本語などのマルチバイト文字以下の例では、ハ
は、3byteなので、str[1]
で参照でき、str[2]と
str[3]`は不正な値としてエラーになります。
nextind()
を使うと、次の文字のインデックスが取得できます。
julia> str = "ハロー、Julia"
"ハロー、Julia"
julia> str[1]
'ハ': Unicode U+30cf (category Lo: Letter, other)
julia> str[2]
ERROR: StringIndexError("ハロー、Julia", 2)
Stacktrace:
[1] string_index_err(::String, ::Int64) at ./strings/string.jl:12
[2] getindex_continued(::String, ::Int64, ::UInt32) at ./strings/string.jl:220
[3] getindex(::String, ::Int64) at ./strings/string.jl:213
[4] top-level scope at REPL[81]:1
julia> str[3]
ERROR: StringIndexError("ハロー、Julia", 3)
Stacktrace:
[1] string_index_err(::String, ::Int64) at ./strings/string.jl:12
[2] getindex_continued(::String, ::Int64, ::UInt32) at ./strings/string.jl:220
[3] getindex(::String, ::Int64) at ./strings/string.jl:213
[4] top-level scope at REPL[82]:1
julia> str[4]
'ロ': Unicode U+30ed (category Lo: Letter, other)
julia> str[nextind(str, 1)]
'ロ': Unicode U+30ed (category Lo: Letter, other)
変数名の前に$
がついた文字列が、文字列内にある場合は、それを変数として展開します。
julia> who = "Julia"
"Julia"
julia> "Hello, $who"
"Hello, Julia"
文字は、Int型の整数にマッピングされているため、大小関係が存在し計算も可能です。
julia> Int('A')
65
julia> Int('a')
97
julia> 'A' < 'a'
true
julia> 'a' - 32
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
正規表現
Juliaで正規表現を使う場合は、r"<正規表現>"
という構文で、Regex型を宣言します。
julia> typeof(r"Ju.*")
Regex
正規表現が対称の文字列に出現するかどうかを調べたい場合は、occursin関数が使えます。 occursin関数は、正規表現が検索対象の文字列に含まれるかどうかを評価しbooleanを返します。
julia> occursin(r"Ju.*", "Julia")
true
julia> occursin(r"Ju.*", "July")
true
julia> occursin(r"Ju.*", "hoge")
false
match関数を使うと、正規表現にマッチした文字列を取得できます。
julia> match(r"(Ju.*)", "Hello, Julia")
RegexMatch("Julia", 1="Julia")
julia> ans[1]
"Julia"
関数
Juliaの関数は、引数から戻り値への写像オブジェクトです。
function <関数名>(<引数>) end
で宣言します。
julia> function f(x)
2x + 1
end
f (generic function with 1 method)
julia> f(1)
3
また、g(x) = 2x + 1
のように宣言することも可能です。
julia> g(x) = 2x + 1
g (generic function with 1 method)
julia> g(1)
3
Juliaの関数は、関数内で最後に評価された式を返却しますが、return
式を使うと明示的に特定の式を返却することができます。
julia> function g(x,y)
return x * y
x + y
end
g (generic function with 2 methods)
julia> g(1,1)
1
無名関数
function
キーワードに関数名を指定しないで関数を定義する。
または、->(アロー演算子)
を使って、無名関数を作ることができます。
julia> x -> x^2 + 2x - 1
#4 (generic function with 1 method)
julia> function(x)
x^2 + 2x - 1
end
#6 (generic function with 1 method)
julia> map(x -> x^2 + 2x + 1, [1, 2, 3, 4, 5])
5-element Array{Int64,1}:
4
9
16
25
36
引数の型
<変数名>::<型>
の形式で引数を宣言することで、関数に渡す引数の型を指定することができます。
julia> function f(x::Int64)
typeof(x)
end
f (generic function with 2 methods)
julia> f(1)
Int64
julia> f("Julia")
ERROR: MethodError: no method matching *(::Int64, ::String)
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...) at operators.jl:529
*(::Missing, ::AbstractString) at missing.jl:170
*(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:54
...
Stacktrace:
[1] f(::String) at ./REPL[8]:2
[2] top-level scope at REPL[33]:1
オプション引数
デフォルト値を設定した引数を持つ関数を定義できます。
julia> function optionalarg(a=10)
a^2
end
optionalarg (generic function with 2 methods)
julia> optionalarg()
100
julia> optionalarg(2)
4
キーワード引数
キーワード引数を定義する事もできます。
キーワード引数は、引数の宣言部分で、;
(セミコロン)の後に記述します。
julia> function keywordarg(x; key=10)
x + key
end
keywordarg (generic function with 1 method)
julia> keywordarg(10, key=100)
110
フロー制御
Juliaのフロー制御には主に以下のものができます。
- ブロック
begin-end
;
チェイン
- 条件分岐
if-elseif-else
- 繰り返し
while
for
- 例外
try-catch
、error
、throw
ブロック
begin-end
や;
チェインを使って、ブロックを作成することができます。
julia> x = begin
a = 100
b = 3
a * b
end
300
julia> x
300
julia> x = (a = 100; b = 100; a + b)
200
julia> x
200
条件分岐
if-elseif-else
で条件分岐することができます。
julia> function f(p::Char)
if p == 'J'
println("Julia")
elseif p == 'P'
println("Python")
elseif p == 'R'
println("Ruby")
else
println("Unknown")
end
end
f (generic function with 3 methods)
julia> f('J')
Julia
julia> f('P')
Python
繰り返し評価
他の多くの言語と同様に繰り返し処理は、while
文かfor
文を使えます。
while
は以下です。
julia> counter = 0
0
julia> while counter < 3
println("counter = $counter")
global counter += 1
end
counter = 0
counter = 1
counter = 2
for
は以下です。
julia> for counter = 0:2
println("counter = $counter")
end
counter = 0
counter = 1
counter = 2
例外制御
組み込み済みの例外は以下のものが用意されています。
- Exception
- ArgumentError
- BoundsError
- CompositeException
- DimensionMismatch
- DivideError
- DomainError
- EOFError
- ErrorException
- InexactError
- InitError
- InterruptException
- InvalidStateException
- KeyError
- LoadError
- OutOfMemoryError
- ReadOnlyMemoryError
- RemoteException
- MethodError
- OverflowError
- Meta.ParseError
- SystemError
- TypeError
- UndefRefError
- UndefVarError
- StringIndexError
例外を投げるには、throw
関数を使います。
julia> function throwerror()
throw(DomainError("test"))
end
throwerror (generic function with 1 method)
julia> throwerror()
ERROR: DomainError with test:
Stacktrace:
[1] throwerror() at ./REPL[51]:2
[2] top-level scope at REPL[52]:1
例外が発生した際の制御は、try-catch
を使います。
julia> try
throw(DomainError("test"))
catch e
println("Catch error")
end
Catch error
まとめ
まだ、全ての機能をさわれていな意ですが、Juliaのマニュアルを読んでどのような機能があるのか確認しました。 数学的な記述方法でコードを書くための機能が充実している印象を受けました。 他にもmacroなどいろいろな機能があるので、後々試してみたいと思います。