Python使いやRuby使いにとってのJuliaの基礎　①文法のさわり

# 序 : Juliaの良さを３行で
- Linux/Mac環境なら導入は簡単
- PythonやRubyのテイストを取り入れた言語なので、データの前処理を簡潔に書けるよ。
- ベクトル、行列、実数・虚数等を扱う数値計算のコーディングを簡潔にできて速い。

(自身が理解できている数式を用いた)数値計算が楽ちんということは、今さら自分が言う必要がないだろうから、ここでは、データマエショリストとして、データの前処理周りにjuliaを使うことを念頭に書いておきたい。PythonやRubyと同じようにデータの前処理を書けるスクリプト言語としても、Juliaが使えるを検証することが目的。

ちょっと補足しておこう:

## 自分的Juliaの良さ① : Windows10のWSLでも簡単導入

たいていのLinuxでは、juliaバージョン1.1は以下の3行で導入できる。

```.sh
curl https://julialang-s3.julialang.org/bin/linux/x64/1.0/julia-1.1.0-linux-x86_64.tar.gz
tar zxvf julia-1.1.0-linux-x86_64.tar.gz
echo 'export PATH="$PATH:/home/kmr/julia-1.1.0/bin"' >> ~/.bashrc
```

すなわち、業務用のWindows10では、謎のウィルス対策ソフトが入っている関係で`apt update`ができなかったりするWSL(Ubuntu)でも導入できるということ。
また、ひとまずJulia1.1が導入できれば、scikit-learnやsparkを使うためのパッケージ導入もサクサクできた(ウィルス対策ソフトの設定次第なのかもしれないが...)。

## 自分的Juliaの良さ② : けっこうbatteries included
`batteries included（バッテリー同梱）`とは、標準ライブラリが充実しているpythonのうたい文句のひとつ。JuliaもディフォルトでDataframeが使えるし、データを扱うための言語機能や標準ライブラリが豊富(なのだと思う)。

周辺ライブラリの充実はまだまだこれからだろうけど、個人的にはなんとかなりそう(postgresへの接続、sparkの活用など)。

## 自分的Juliaの良さ③ : Fortranに替えての、今風の教育用言語になりそう

中高一貫校あたりに通っていて方程式を覚え始めたばかりの中学生くらいの教育用言語として、juliaははまる気がする。
子供たちに数値計算を教える時に、良いのではと思ったり。

数値計算ならば、まずは、C/Fortran書かねばという方々は、アセンブラからC/Fortran作るところから始める別の道を作ってくださいませ。

# Juliaの基礎知識
「Python使いやRuby使いが」と題したものの、以下、1.0以前のJuliaの分かりやすい解説である[『PythonistaのためのJulia入門』](https://qiita.com/CORDEA/items/6164b3d1465c3c1a195a)をフォーク(?)させてもらう形で、Python使いがJuliaを使う必要に迫られた際に覚えておくべき構文などをメモしていきます。Rubyはワンライナー書く時くらいにした使わないもので。
ただし、そもそもJuliaの文法はどちらからというRuby寄りだし、今やPythonも書けるRubyistも多いだろうから、Rubyistの皆さんも斜め読みしてください。なお、以下、Juliaのバージョンは1.1で。
なお、Juliaの導入法などは省いているので、そのあたりは、[Julia 入門①](https://qiita.com/torininaritahi/items/6a3a431e1341e9057877)などをご参考に。

まずは、REPLでハローワールド。

```julia
julia> print("Hello World!")
Hello World!
```

また、juliaでは(Fortranと同じく)listなどのindexは0からではなく **1** から始まる。
※　コードは`;`で区切ることで、1行で書くことができる。

```julia
julia> List = [0, 1, 2];print(List[1])
0
```

文字列のスライスも、同じくindexは**1** からであること確認しておこう。
※　スライスはpython風の表記。ブロックの考え方はrubyに近い。

```helloworld2.jl
s = "hello julia world."
for n = s[7:11]
    print(n)
end
println()
for n = s[13:18]
    println(n)
end
```

ワンランナーにしておこう:
※　print関数は改行なし、println関数は改行あり。

```julia

julia> s = "hello julia world."; for n = s[7:11];print(n);end; println(); for n = s[13:18];println(n);end
julia
w
o
r
l
d
.
```

なお、文字列はfor文中で、直接扱える(イテレータということだろうね)。

```julia
julia> for s = "aiueo";println(s);end
a
i
u
e
o
```

## 付記　C言語風のprintf
Printfパッケージを使えば、C言語風のprintfを行える。
参考:
https://qiita.com/CORDEA/items/6164b3d1465c3c1a195a#printf

```julia
julia> e = ℯ
ℯ = 2.7182818284590...

julia> typeof(e)
Irrational{:ℯ}

julia> str  = "オイラー数"
"オイラー数"

julia> using Printf

julia> @printf "%sは、%f に近似されるIrrationalである。" str e
オイラー数は、2.718282 に近似されるIrrationalである。
```
printfマクロではカッコやカンマが省略できる。

# 制御構造(Control flow)
取り急ぎ、forとif周りと例外処理を押さえておこう。

## for Loop statements

pythonで`for i in range(10)`と書くところ、Juliaはスライスで書く。

```julia
for n = 0:9
	println(n)
end
```

イコールの代わりに、`for x in イテレータ`といった形でも書ける。

```julia

julia> for n in 0:9;print("$n.");end
0.1.2.3.4.5.6.7.8.9.
```
個人的には、julia使う時は何かを計算したいという時だろうから、なるべくイコールをガンガン書きたい。
$nのところは、モダンな言語のたしたみ、string interpolation(文字列補間)。

## If statements
pythonで`if～elif～else`であるところ、juliaでは`if～elseif～else`。
また、Juliaでは、`and`は`&&`、`or`は`||`となる。

```julia
hoge = "hoge"
if hoge[1] == 'h' && hoge[2:4] == "oge"
	println("hoge is hoge")
elseif hoge == "huge" || hoge == "hige"
	println("hoge is huge or hige")
else
	println("hoge is ", hoge)
end
```
## 応用: ifとforを組み合わせてのList complemention
List complemention(内包表記)が、pythonと同様につかえる。

```julia
julia> [x^3 for x in 0:9]
10-element Array{Int64,1}:
   0
   1
   8
  27
  64
 125
 216
 343
 512
 729
 ```

マイナスにステップするイテレータと組み合わせると:

```julia
julia> [x for x = 5:-2:-5]
6-element Array{Int64,1}:
  5
  3
  1
 -1
 -3
 -5
``` 
後置ifと組み合わせることもできる。

```julia
julia> [x for x in 0:30 if x % 5 == 1 ]
6-element Array{Int64,1}:
  1
  6
 11
 16
 21
 26
 ```
 
juliaらしく、虚数を扱う例もおまけに:

```julia
julia> [[x + y * im for y = -2:3] for x = 0:4]
5-element Array{Array{Complex{Int64},1},1}:
 [0-2im, 0-1im, 0+0im, 0+1im, 0+2im, 0+3im]
 [1-2im, 1-1im, 1+0im, 1+1im, 1+2im, 1+3im]
 [2-2im, 2-1im, 2+0im, 2+1im, 2+2im, 2+3im]
 [3-2im, 3-1im, 3+0im, 3+1im, 3+2im, 3+3im]
 [4-2im, 4-1im, 4+0im, 4+1im, 4+2im, 4+3im]
 ```
内包表記は行列を扱う際にも使える。

```julia
julia> A = reshape([x^2 for x in 0:11], 3,4)
3×4 Array{Int64,2}:
 0   9  36   81
 1  16  49  100
 4  25  64  121
```

Juliaでは、行列は簡単に転置ができる。

```julia
julia> A'
4×3 LinearAlgebra.Adjoint{Int64,Array{Int64,2}}:
  0    1    4
  9   16   25
 36   49   64
 81  100  121
```

## Exception Handling (例外処理)

例外処理は、try～catchでおこなえる:

```err.jl
vec = [x for x = 5:-2:-5]

for i in 1:8 
    try
        println("$(vec[i])の平方根は、$(√vec[i])")
    catch e
        println("Err! : ",e)
    end
end
```

実行結果:
>$ julia err.jl
5の平方根は、2.23606797749979
3の平方根は、1.7320508075688772
1の平方根は、1.0
Err! : DomainError(-1.0, "sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
Err! : DomainError(-3.0, "sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
Err! : DomainError(-5.0, "sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
Err! : BoundsError([5, 3, 1, -1, -3, -5], (7,))
Err! : BoundsError([5, 3, 1, -1, -3, -5], (8,))


# 関数・函数
## 基礎
pythonのdefの代わりはjuliaではfunction(関数)だが、7文字もあるのは嫌なので、
個人的には、数学的なイコール表記のmethods(自分訳:函数？)で押し通すことにしている。

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

julia> [[ add(x,y) for y = 0:3] for x = 0:2]
3-element Array{Array{Int64,1},1}:
 [0, 1, 2, 3]
 [1, 2, 3, 4]
 [2, 3, 4, 5]

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

julia> [[ add(x,y) for y = 0:3] for x = 0:2]
3-element Array{Array{Int64,1},1}:
 [0, 1, 2, 3]
 [1, 2, 3, 4]
 [2, 3, 4, 5]
```
Juliaの基礎知識として、function(関数)・methods(函数)がコンパイルの単位となることがある。
コンパイル後はインタープリタ実行に比べ相当に(私の環境では約100倍)、実行速度が速くなる。
コードの見通しも良くなるし使わない手はない。

函数も、let～endでブロックを作ることで副作用のある操作を書ける。
前述のif文をもとに、函数を作ってみる。

```hoge.jl
isHoge(h)= let
  print(h*"を受け取りました: ")
	if h[1] == 'h' && h[2:4] == "oge"
		"hoge is hoge."
	elseif h == "huge" || h == "hige"
		"hoge is not huge or hige."
	else
		"hoge is not $(h)."
	end
end

for s = "aiueo"
    ret = isHoge("h$(s)ge")
    println(ret)
end
```

等号が入ることでぱっと見、Ocamlやscalaなどの関数型言語に近い見た目となる。

実行結果:
> $ julia hoge.jl
hageを受け取りました: hoge is not hage.
higeを受け取りました: hoge is not huge or hige.
hugeを受け取りました: hoge is not huge or hige.
hegeを受け取りました: hoge is not hege.
hogeを受け取りました: hoge is hoge.


## Anonymous Functions(匿名函数)

pythonの` lambda x, y : x + y `は、juliaでは、`(x, y) -> x + y`。
pythonのlambdaは可読性が低いと感じているため、これはうれしい。
なお、juliaの場合、関数・函数の引数xやyには、整数・有理数の他、和(足し算)が成り立つ無理数や虚数も取ることができる(もちろん、無理数は近似値を返す)。


```julia
julia> z = (x, y) -> x + y
#3 (generic function with 1 method)

julia> z(-2,3)
1

julia> z(im,3-2im)
3 - 1im

julia> z(im, .3)
0.3 + 1.0im

julia> z(im,π)
3.141592653589793 + 1.0im

```

## ファイルを扱う関数の例
データ前処理に欠かせない、ファイルの読み書きを扱う関数を見ておこう。
ファイルの読み書きでは、pythonの`with open(ファイル名) as f`と同じような`open(ファイル名) do f`といった書き方をする。

### Read
```loadrile.jl
open("hoge.jl") do f
	for line in eachline(f)
		println(line)
	end
end
```

### Write

先ほどのisHoge函数の出力をファイルに書き出す場合:

```julia
open("hogeout.txt", "w") do f
    for s = "aiueo"
        ret = isHoge("h$(s)ge")
        write(f, "$(ret)\n")
	end
end

```

# クラス

Julisにクラスは無い。これはCやNimなどと同様で潔い。
もちろん、やろうと思えば、オブジェクト指向プログラミングはできる。
興味がある方は、Julia界の日本人エバンジェリスト黒木先生のツイートをどうぞ:
https://twitter.com/genkuroki/status/978716550268993536?lang=ja

# 続く
Dataframeやデータベースの扱いなどは、データ前処理編にて。