Julia その１

Juliaという言語がある。Amazon.co.jpでぐぐると18禁ページにとばされそうになってびっくりする。

JuliaboxというサイトでJupyter ノートブックで使える。言語としてはRubyとかPythonとかのようなスクリプト言語のように見えるが実はなかなかハードコアで、動的に特定の型に特化されたバージョンがJITでコンパイルされて動作するのでかなり速い、らしい。

結構特徴的な言語仕様なので、面白いところを紹介する。

## 1オリジン
Juliaはコンピュータサイエンティスト向けというよりは数学者向けの言語で、その証拠に、配列の添字が１で始まる。配列の添字が１で始まる言語はRとかその前身のSとか、古のFortranとか、APLとか、数学者向けなのだ。コンピュータ屋にとっては配列のインデックスはベースアドレスに足す数なので、１オリジンとか気が狂ってるように見えるのだけど、数学者にとっては「０番目の要素」とか言われるとやっぱり気が狂っているように見えるのだろう。

```
> a = [1,2,3]
> a[1]  
1
```

これがPythonだと当然下のようになる。なれるまでは時間かかりそう。

```
> a = [1, 2, 3]
> a[1]
2
```
## ans
REPLの中ではansという変数が特殊な変数扱いになっていて、直前の入力の評価結果になる。

```
julia> 1+1
2
julia> ans
2
```

スクリプトとして使うときには当然使えない。



##係数の書き方

数学だと`2x`と書くと2かける`x`という意味になり、係数が省略できるが、一般のプログラミング言語では、`2 * x`のように掛け算であることを明示する必要がある。ところがJuliaでは`2x`のように直接書くことができる。スペースを開けるとエラーになる。数字で始まる変数名は許されないのでパーズできるのだろう。変数名が`e`とかだと指数表記との区別が結構面倒なコーナーケースがありそうだけど問題ないのだろうか。

試してみたら案の定、結構面倒。

```
> x = 2
> 2x+1
5  # 2 * 2 + 1
```

だが、

```
> e = 2
> 2e+1
20 #  2 * 10 ^ 1
```

となる。。。数値の後に`e+` もしくは`e-`がくるとパースを変えるようだ。割にアドホック。
変数名としてeを使ってはいけない、ということだな。

## 変数名
任意のユニコード文字が変数として使える。それは今どきの言語としては別に珍しくもないが、JuliaのREPLにはlatexライクなギリシャ文字変換機能がついているので、かな漢字変換の無い環境のユーザにも使いやすくなっている。例えばπであれば`\pi`とうってからtab で`π`に変換される。

ちなみに`π`には円周率（の近似値）がはじめから入っている。便利だ。

```
julia> π
π = 3.1415926535897...
julia> sin(0.5π)
1.0
```

変数名は些細な話のようにも思えるけど、数式を引き写すときにはかなり便利っぽい。`μ`とか`σ`とかをそのまま使えるのはよい。。

REPLで変換できる文字のリストがここにある。恐ろしい数が定義されているけど、区別がつかないものも多数。。

https://docs.julialang.org/en/v1/manual/unicode-input/index.html

## 有理数

分子と分母の2つの整数で表す有理数もサポートされている。
python の fractions と同じような機能だが、言語で直接サポートされているので、ずっと書きやすい。`//`で区切って書く。

```
julia> 1//3 * 3
1//1
```
有理数と浮動小数点を足すと浮動小数点になる。
```
Julia> 1//3 * 3.0
1.0
```
有理数と整数の演算は、有理数のまま。
```
julia> 1//3 * 3
1//1
```

分子部分を取り出すには`numerator`、分母部分を取り出すには`denominator`を用いる。

```
julia> numerator(2//3)
2
julia> denominator(2//3)
3
```
## 複素数
Juliaは複素数をネイティブでサポートしている。算術演算系の演算子も複素数をサポートしている。すごい。リテラルとしては虚数単位を予約変数`im`で書く。

```
julia> typeof(1 + 1im)
Complex{Int64}
julia> typeof(1 + 1.0im)
Complex{Float64}
```

算術演算子が複素数をサポートしているので、例えばオイラーの公式の左辺をこんなふうに書くことができる。 `ℯ`は`e`ではなくて、自然対数の底を表すいわゆるネイピア数で、`π`同様もともと定義されている。REPLからだと\euler + tab で出すことができる。

```
julia> f(θ) = ℯ^(im * θ)
f (generic function with 1 method)
julia> f(π)
-1.0 + 1.2246467991473532e-16im
```

うーん素晴らしい。
ちょっと面白いのは`sqrt`の挙動。`sqrt(-1)`は実数の範囲には解がないので、エラーが出る。でも、複素数なら解があるのでちゃんと動く

```
julia> sqrt(-1.0)
ERROR: DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:31
 [2] sqrt(::Float64) at ./math.jl:492
 [3] top-level scope at none:0

julia> sqrt(-1.0 + 0.0im)
0.0 + 1.0im
```

リテラルとしてではなく複素数を作るには`complex`関数を用いる。実部、虚部を取り出すにはそれぞれ`real`、`imag`を、共役数を得るには`conj`を用いる。`angle`は実軸からの回転角を返す。

```
julia> c = complex(1.0 + 1.0im)
1.0 + 1.0im
julia> real(c)
1.0
julia> imag(c)
1.0
julia> conj(c)
1.0 - 1.0im
julia> angle(c)
0.7853981633974483
```


## 割り算系演算子

ちなみに、Python3では`//`は商の整数の部分を表す。整数同士の割り算が浮動小数点を返すという仕様のせい。

```
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
```
実はJuliaも同じように、整数の割り算結果が浮動小数点で返される。では`//`に当たる演算子はどうなっているのかというと、なんと`÷`を使う。これは`\div + tab`で出せる。

```
julia> 10 / 3
3.3333333333333335
julia> 10 ÷ 3
3
julia> 10 % 3
1
```

このように普通のキーボードで直接打てない演算子は他にもいくつかあるようだ。昔あったAPLはおかしな記号だらけだったけど、それに近いものを感じる。。しかし、REPLではlatex記法で打てるにしても、エディタでプログラムを書く場合にはどうやって出すんだろうか。われわれ日本人はIMEでなんとかなるが。

さらに！`\`という演算子も定義されている。`a \ b` は `b / a`と等価。これいるかなあ。。

```
julia> 10 \ 3
0.3
```