知っていて当たり前-11　その他の関数

# 知っていて当たり前-11　その他の関数

## 1.　式の評価 `eval()`

文字列を式として評価（実行）する。


```julia
eval(Meta.parse("1 + 2"))
```




    3



`Meta.parse()` は，Julia の抽象構文木(AST) を表す Expr 型のオブジェクトを返す。


```julia
Meta.parse("1 + 2")
```




    :(1 + 2)




```julia
typeof(Meta.parse("1 + 2")), typeof(:(1 + 2))
```




    (Expr, Expr)




```julia
eval(:(1 + 2)) # つまり eval(Meta.parse("1 + 2")) と同じ
```




    3



文字列，Expr の中では `$` による補間も使える。


```julia
a = 3
eval(Meta.parse("1 + $a"))
```




    4




```julia
eval(:(1 + $a))
```




    4



### 1.1.　関数を定義する例


```julia
func = "add"
eval(Meta.parse("$func(a, b) = a + b"))
add(10, 20) # 30
```




    30



## 2.　パイプ `|>`

多くの関数型のプログラム言語では，処理を行うために関数を入れ子で書くことが普通であった。


```julia
inv(sum(x -> x.^2, [1:5;]))
```




    0.01818181818181818



データを「パイプ演算子 `|>`」 で次の関数の引数として渡すような書き方をすれば，処理の順番にプログラムを書くことができる。



```julia
[1:5;] |> x -> x.^2 |> sum |> inv
```




    0.01818181818181818



適用する関数が複数の引数を保つ場合には，無名関数を使うことによって任意の位置の引数に渡すことができる。


```julia
using RDatasets, DataFrames
iris = dataset("datasets", "iris");
select(iris, :SepalLength) |> x -> first(x, 5)
```




<div class="data-frame"><p>5 rows × 1 columns</p><table class="data-frame"><thead><tr><th></th><th>SepalLength</th></tr><tr><th></th><th title="Float64">Float64</th></tr></thead><tbody><tr><th>1</th><td>5.1</td></tr><tr><th>2</th><td>4.9</td></tr><tr><th>3</th><td>4.7</td></tr><tr><th>4</th><td>4.6</td></tr><tr><th>5</th><td>5.0</td></tr></tbody></table></div>



ベクトルをパイプで関数ベクトルにつなげると，要素に対応した関数が適用される。


```julia
["a", "list", "of", "strings"] .|> [uppercase, reverse, titlecase, length]
```




    4-element Vector{Any}:
      "A"
      "tsil"
      "Of"
     7



## 3.　関数の合成 `∘`

`f（g（x））` は 関数 `g` に引数 `x` を与えた結果を関数 `f` の引数にすることである。

「合成演算子 `∘`」 を使って `(f ∘ g)(x)` と書くことができる。


```julia
sqrt(sum(1:10))
```




    7.416198487095663




```julia
(sqrt ∘ sum)(1:10)
```




    7.416198487095663




```julia
1:10 |> sum |> sqrt
```




    7.416198487095663




```julia
map(first ∘ reverse ∘ uppercase, split("you can compose functions like this"))
```




    6-element Vector{Char}:
     'U': ASCII/Unicode U+0055 (category Lu: Letter, uppercase)
     'N': ASCII/Unicode U+004E (category Lu: Letter, uppercase)
     'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)
     'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
     'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)
     'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)



## 4.　リスト内包表記

リスト内包表記は Python での用語で，Julia ではリスト内包表記というのは変だと思う。Julia では `["123", "45", "6789"]` はリストではないから。

Julia では，これを使う意味はない（使ってはならない）。for ループで書けば 10万倍速い（後述）。


```julia
[parse(Int, i) for i in ["123", "45", "6789"]]
```




    3-element Vector{Int64}:
      123
       45
     6789



### 4.1.　`enumerate()` を使う場合

`enumerate(x)` は 添字（インデックス）とベクトルの要素を同時に使用する。


```julia
[println("$i, $j") for (i, j) in enumerate(["123", "45", "6789"])]
```

    1, 123
    2, 45
    3, 6789





    3-element Vector{Nothing}:
     nothing
     nothing
     nothing



### 4.2.　`zip()` を使う場合

`zip(a, b, ...)` はそれぞれのベクトルの要素を同時に使用する。


```julia
[println("$i, $j") for (i, j) in zip(["123", "45", "6789"], ["a", "b", "c"])]
```

    123, a
    45, b
    6789, c





    3-element Vector{Nothing}:
     nothing
     nothing
     nothing




```julia
@time x = [sqrt(i) for i in 1:100000000];
```

      0.237202 seconds (47.67 k allocations: 765.485 MiB, 2.92% gc time, 6.48% compilation time)



```julia
@time for i in 1:100000000
    sqrt(i)
end
```

      0.000001 seconds


### 4.3.　後置 if を使う場合

後半に `if ...` がある場合には，`foo in bar` 中の `foo` が `if` の条件を満たすものに対してのみ処理が行われる。


```julia
[i^2 for i in 1:10 if i % 2 == 0]
```




    5-element Vector{Int64}:
       4
      16
      36
      64
     100



### 4.4.　二重の内包表記

for を 1 回書くのと，2 回書くのでは違いがでてくる。


```julia
[10a + b for a=1:3, b=8:9]
```




    3×2 Matrix{Int64}:
     18  19
     28  29
     38  39




```julia
[10a + b for a=1:3 for b=8:9]
```




    6-element Vector{Int64}:
     18
     19
     28
     29
     38
     39



## 5.　辞書内包表記 `Dict()`

応用すべき例が思いつかない。


```julia
a = Dict(k for k = zip(["jp","USA","UK"], [0,1,2]))
```




    Dict{String, Int64} with 3 entries:
      "USA" => 1
      "UK"  => 2
      "jp"  => 0