View on GitHub

julia-doc

Julia入門

はじめに

Julia の紹介・特徴

インストール

Julia は Windows / Mac / Linux、どれでも簡単にインストールできます。ダウンロードページ から Current stable release(最新安定版)の該当する OS のインストーラを選択します。2022/8/26 時点では v1.7.2 が最新安定版です。例えば64ビット版の Windows であれば、「Windows」の「64-bit (installer)」 をダウンロード・実行すれば特に何もすることはありません。

上記の方法でうまくいかない場合はソースインストールを試みてみましょう。例えば Linux の場合、「Source」の「Tarball with dependencies」をダウンロードし、

$ tar xvzf julia-1.8.0-full.tar.gz
$ cd julia-1.8.0
$ make

とすればコンパイルできます。必要に応じて実行バイナリ(julia)へパスを通せば完了です。なお、ソースインストールは一般ユーザでも可能です。

はじめての Julia

julia をダブルクリックやコマンドプロンプトから実行すると、対話的にコマンドを実行する REPL (read-eval-print loop) が立ち上がります。 <!– テキスト:julia立ち上げ時の様子

Jupyter notebook を使っている場合は、以下のような画面になります。

図: –>

ここで julia の様々なコマンドを入力することで、処理が実行されます。結果は即座に表示されます。

julia> 1 + 2
3

なお、行の末尾にセミコロン(;)を付けると結果は即座に表示されないようになります。また、Jupyter notebook では、最後に処理した行の結果が表示されます。

明示的に表示したい場合は println() を使います。

julia> println("Hello Julia!")
Hello Julia!

REPL を終了するには exit() と入力します。

モード

REPL では処理に応じてモードを切り替えます。

julia モード

julia を立ち上げた直後のモードは julia モードと呼ばれています。これは julia コマンドを受け付けて処理を行うモードであり、プロンプトにはjulia> と表示されます。julia 以外のモードにおいてバックスペースを入力すると、julia モードへ戻ることができます。

ヘルプ(help)モード

julia モードにおいてクエスチョンマーク(?)を入力するとヘルプモードに入ります。ヘルプモードにおいてキーワードを入力すると、関連するドキュメントが表示されます。

もしくは、クエスチョンマークに続いてコマンド名を入力してもOKです。

julia> ?transpose()
cos(x)

Compute cosine of x, where x is in radians.

See also [cosd], [cospi], [sincos], [cis].

パッケージ(pkg)モード

julia モードにおいて右角括弧(])を入力するとパッケージモードに入ります。パッケージをインストールする際に利用します。

julia> ]
(@v1.4) pkg> add PyPlot

シェル(shelll)モード

セミコロン(;)を入力するとシステムのシェルのコマンドを受け付けるシェルモードに入ります。Windows では機能しないようです。

継続行

Julia で1行のコードを複数行に分ける汎用的な記述方法はありません。但し、ある行が完全な式で終了していない場合、次の行へ継続すると解釈されます。例えば、ある行で括弧が閉じていなければ継続行とみなされます。

スクリプトファイルの実行

julia コマンドにスクリプト名を渡すと、スクリプトを実行できます。

$ julia test.jl

スクリプトの実行が終了すると julia も終了して呼び出し元に戻ります。実行が終了した後も引き続きREPLで julia を使いたい場合は、オプション -i をつけて実行します。

$ julia -i test.jl

コマンド名に続いて引数を指定すると、julia から配列変数 ARGS によって参照することができます。

$ julia -i test.jl aaa bbb
...
julia> ARGS[1]
aaa

REPL からスクリプトを実行することもできます。この場合は、include() を利用します。

julia> include("test.jl")

include() はオーバーヘッドが少ないため、デバッグには重宝します。但し、REPLを立ち上げながら複数回実行すると複数回評価されることになるので注意が必要です。また、引数を与えることはできず、最初に実行した時の引数がそのまま残ります。

変数

ある値を指す(格納する)文字列を変数と言います。多くの他言語では事前の型宣言が必要ですが、Julia では型宣言なしにそのまま利用できます。

代入と参照

代入演算子(=)を利用すると、右辺で指定した値を左辺の変数へ代入できます。

julia> x = 1
1
julia> y = 2.5
2.5
julia> str = "Hello!"
Hello!

値の参照は、単に変数名を指定するだけです。

julia> y
2.5

但し、クオーテーションの中から参照したい場合は、ダラー($)を変数名の前に付けます。

julia> println("y = $y")
y = 2.5

変数名

Julia の変数名は大文字・小文字の区別があり、アルファベット(A-Z, a-z)、アンダースコア(_)、又は Unicode の 00A0 以上で開始する必要があります。2文字目以降についてはさらに数値(0-9)、エクスクラメーション(!)、シングルクオーテーション(’)、および他の Unicode 文字を利用することが可能です。但し、if や for といった予約語を変数名として利用することはできません。

アンダースコアのみで構成される変数は、代入のみ可能で参照できない、という少し特殊な性質を持っています。これは、例えば以下のようにダミーで変数を受け取りたい時に役に立ちます(アンダースコアは何個でも構いません)。

___, y = size([1 2 3; 4 5 6])
println(y) -> 3

変数名として利用可能な Unicode 文字の詳細については、本家の Allowed Variable Names を参考にしてください。

Julia の予約語

baremodule, begin, break, catch, const, continue, do, else, elseif, end, export, false, finally, for, function, global, if, import, let, local, macro, module, quote, return, struct, true, try, using, while

変数名の慣習

Julia本家ドキュメント によると、変数名には以下に従うことがおすすめされています(強制ではありません)。

スコープ

変数のスコープとは、変数が参照可能なコードの領域です。Julia のスコープは大域(global)スコープと局所(local)スコープに分類されます。

基本的な型

整数

浮動小数点

複素数

虚数単位を表す変数として、定数 im が予め定義されています。1 + 2i を変数 x に代入する例を示します。

julia> x = 1 + 2im
1 + 2im

複素数を含む演算についても、実数と同様に行うことができます。

複素数から実部、もしくは虚部を実数として取り出すには、関数 real()imag() を利用します。

julia> real(x)
1

julia> imag(x)
2

絶対値は abs()、複素共役は conj()、偏角は angle() によって得ることができます。

julia> angle(x) / 2pi * 360
63.43494882292201

分数

演算

主要な関数一覧

Base パッケージに含まれる主要な関数を紹介します。

丸め関数

関数 説明 戻り値
round(x) x を最も近い整数に丸める typeof(x)
round(T, x) (同上) T

配列

生成

配列を生成するにはいくつかの方法があります。まずは関数 Array() を用いた最も基本的な方法を示します。

Array{型}(undef, 次元...)

例えば倍精度実数で 2x3 の2次元配列 a を作成する場合、

julia> a = Array{Float64}(undef, 2, 3)

と記述します。なお、a は初期化されないため、格納されている値は不定です。

julia> a
2×3 Matrix{Float64}:
 1.40837e-315  9.10338e-316  1.40837e-315
 1.00098e-315  1.41457e-315  9.10182e-316

最初から値を埋めたい場合は zeros()ones()、もしくは fill() を使いましょう。

zeros([型=Float64,] 次元...)
ones([型=Float64,] 次元...)
fill(値, 次元...)

zeros() は 0 埋め、ones() は 1 埋め、fill() は任意の値を埋めます。fill() については値の型がそのまま配列の型になります。以下は使用例です。

julia> a = zeros(Int32, 2, 3)

julia> b = ones(Float64, 2, 2, 2)

julia> c = fill(1, 10)

配列リテラル

値を羅列することで配列を生成することもできます。以下のように大括弧[]の中にコンマ区切りで値を羅列することで、1次元配列(列ベクトル)を生成することができます。要素の値に応じて型が自動的に決定されます。

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

julia> b=[1.1, 2.2, 3.3]
3-element Vector{Float64}:
 1.1
 2.2
 3.3

julia> println(b)
[1.1, 2.2, 3.3]

julia> eltype(b)
Float64

2次元配列(行列)を作成する場合、行の各要素は空白またはダブルセミコロン(;;)で区切り、縦方向はセミコロン(;)もしくは改行で区切ります。

julia> [1 2 3; 4 5 6]
2×3 Matrix{Int64}:
 1  2  3
 4  5  6

julia> [1 2 3
        4 5 6]
2×3 Matrix{Int64}:
 1  2  3
 4  5  6

以上の応用として、列ベクトルを行方向に並べる形で行列を作成することも可能です。

julia> [[1,4] [2,5] [3,6]]
2×3 Matrix{Int64}:
 1  4  7
 2  5  8

配列のコピー

配列をコピーする場合は copy() を利用します。

julia> a = copy(b)

なお、= を用いた代入を用いると、b を変更すると a にも反映されてしまいます。これは、Julia の関数が共有渡しで引数を渡していることと関係しています。

演算子

配列に対して以下の演算子を利用することができます。演算結果は配列で返ります。単なる乗算のように、配列の各要素に対して演算したい場合はブロードキャストを使いましょう。

演算子 名前 補足
+ 単項+ 特に何もしない
- 単項- 正負を反転
演算子 名前 補足
+ 加算  
- 減算  
* 内積  
/   x / yx * inv(y) と等価
\   x \ yinv(x) * y と等価
^ べき乗 x ^ yxy
演算子 名前 意味
== 等価  
!= 非等価  

配列の結合

vcat() は与えられた配列を1次元目方向につなげていきます。特に行列(2次元配列)を縦方向に追加していく場合に便利です。

julia> a = [1 2 3 4]
1×4 Matrix{Int64}:
 1  2  3  4

julia> b = [10 20 30 40; 100 200 300 400]
2×4 Matrix{Int64}:
 10   20   30   40
100  200  300  400

julia> c = vcat(a,b)
3×4 Matrix{Int64}:
  1    2    3    4
 10   20   30   40
100  200  300  400

行列を横方向に追加したい場合は hcat() を使いましょう。これは与えられた配列を2次元目方向につなげていきます。

julia> a = [1 2 ; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> b = [10 20 30 40 ; 100 200 300 400]
2×4 Matrix{Int64}:
  10   20   30   40
 100  200  300  400

julia> c = hcat(a,b)
2×6 Matrix{Int64}:
 1  2   10   20   30   40
 3  4  100  200  300  400

vcat()hcat() ともに、引数としていくらでも配列を与えることができます。但し、vcat() であればそれぞれの配列の1次元目、hcat() であればそれぞれの配列の2次元目を除く各次元の要素数が一致する必要があることに注意が必要です。

以下に配列の結合に関連した関数をまとめておきます。 | 関数名 | 意味 | |:—– |:—————————| | vcat(a,...) |a, … の縦結合| | hcat(a,...) |a, … の横結合| | cat(a,...; dims) |a, … の汎用的な結合|

その他の配列関数

| 関数名 | 意味 | |:—– |:—————————| | transpose(a) |aの転置(aは1-2次元配列)| | adjoin(a) or a' |aの随伴行列(aは1-2次元配列)。すなわち、aを転置して各要素について複素共役をとって得られる行列。各要素が実数の場合はaの転置と等価|

その他

文字列

基本

文字列はダブルクオーテーション(”)、もしくは3連続のダブルクオーテーション(””“)で囲みます。

julia> a = "abc"
"abc"
julia> b = """abc"""
"abc"
julia> c = """He said "Yes"."""
"He said \"Yes\"."

このように、ダブルクオーテーションを含む文字列の場合はエスケープ文字(\)を利用してもよいのですが、3連続のダブルクオーテーションで囲むのが便利です。

文字列を参照する場合は通常の変数と同様、変数名をそのまま利用します。ダブルクオーテーションの中で参照したい場合は、ドル記号($)を用いて参照することもできます。

julia> a = "abc"
"abc"
julia> a
"abc"
julia> "a = $a"
"a = ABC"

部分文字列を取り出したい場合は、配列と同様に範囲を指定します。

julia> a = "abc"
"abc"
julia> a[1:2]
"ab"

結合

文字列の結合には string()、もしくはアスタリスク(*)を使います。他の言語のように + や // 等を用いないことに注意が必要です。

julia> a = "abc"
"abc"
julia> b = "ABC"
"ABC"
julia> c = string(a, b)
  "abcABC"
julia> d = a * b
"abcABC"

別の方法として、ドル記号($)を用いる方法もあります。

julia> e = "$a$b"
"abcABC"

条件分岐

条件に合致した時に実行される構文です。

if-elseif-else文

文法は以下の通りです。

if condition-1
     ...
elseif condition-2
    ...
else
    ...
end

なお、elseif および else ブロックは省略可能です。

繰り返し

break: ループから抜ける

関数

入力した値に対して戻り値を返す仕組みを関数といいます。

定義

関数は functionend で囲んで定義します。以下が基本形です。

function func(args...)
    ...
    return ret
end

戻り値は return で返します。関数の途中に return がある場合はその後から関数末尾までの処理は実行されません。

以下は2つの引数の和を返す関数の例です。

julia> function add(x, y)
           return x + y
       end
add (generic function with 1 method)

Julia の関数の面白い特徴として、return を省略すると最後に評価された式の値が返ります。従って、上の関数は以下のように記述することも可能です。

julia> function add(x, y)
           x + y
       end
add (generic function with 1 method)

このように一行で記述できるような関数の場合、さらに簡略化した代入形式(assignment form)を利用することもできます。

julia> add(x,y) = x + y
add (generic function with 1 method)

呼び出し

関数を実際に利用する呼び出しは以下のような形で行います。

func(args...)

さきほどの add 関数を利用する例を示します。

julia> add(2, 3)
5

このように、入力した値に対して答えを返すのが関数の役割といえます。

値の受け渡し

Julia における関数の引数は、共有渡し(pass-by-sharing)で渡されます。大ざっぱには、引数の型の種類に応じて以下のように動作します。

具体的な例でみていきましょう。

julia> function addv(x, y)
         x = x + y
       end
addv (generic function with 1 method)
julia> p=2
       addv(p, 5)
       p
2

このように、関数内で引数の値を変更しても、呼び出し元には反映されません。

一方、配列を引数として渡すと、関数内での変更が呼び出し元にも反映されます。

julia> function addvarray!(x, y)
         x[1] = x[1] + y
         x[2] = x[2] + y
         x[3] = x[3] + y
       end
addvarray! (generic function with 1 method)
julia> a=[1,2,3]
       addvarray!(a,3)
       a[1]
4

無名関数(anonymous functions)

後述の理由により、名前のない関数を定義することがあります。無名関数と呼ばれるこのような関数は、

function (args...)
    ...
end

のように関数名を省略する、もしくはさらに省略して、

args -> ...

のような文法で定義できます。

無名関数は、関数の引数として関数を渡す場合によく用いられます。以下は、1, 3, -1 それぞれを引数とする無名関数の結果を得る例です。

julia> map(x -> x^2 + 2x - 1, [1, 3, -1])
3-element Vector{Int64}:
  2
 14
 -2

doブロック構文

関数の引数として関数を渡す方法は有用ですが、無名関数の定義が長い場合は引数の部分が冗長になってしまいます。このような場合、以下のdoブロック構文で書き換えるとより分かりやすい記述になる場合があります。

func( args-for-func-except-1st-arg ) do args-for-anonymous-func
  ...
end

たとえば、前述の

map(x -> x^2 + 2x - 1, [1, 3, -1])

は、

map([1, 3, -1]) do x
    return x^2 + 2x - 1
end

のような形で書き換えることが可能です。