Elixir 練習問題 ListsAndRecursion-8

^o^ > elixir practice_10_4.exs
[total_amount: 107.5, id: 123, ship_to: :NC, net_amount: 100.0]
[total_amount: 35.5, id: 124, ship_to: :OK, net_amount: 35.5]
[total_amount: 25.92, id: 125, ship_to: :TX, net_amount: 24.0]
[total_amount: 48.384, id: 126, ship_to: :TX, net_amount: 44.8]
[total_amount: 26.875, id: 127, ship_to: :NC, net_amount: 25.0]
[total_amount: 10.0, id: 128, ship_to: :MA, net_amount: 10.0]
[total_amount: 100.0, id: 129, ship_to: :CA, net_amount: 100.0]
[total_amount: 53.75, id: 130, ship_to: :NC, net_amount: 50.0]

total_amount が最初に追加されちゃってるのがちょっと気に入らないけど、まあいいか。

Elixir 練習問題 ListsAndRecursion-7

以前に作った span 関数と内包表記を使って 2 から n までの素数。

^o^ > iex practice_10_3.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.primes(50)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Elixir 練習問題 ListsAndRecursion-6

flattenn

^o^ > iex practice_10_2.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.flatten([1, [2, 3, [4] ], 5, [[[6]]]])
[1, 2, 3, 4, 5, 6]

Elixir 練習問題 ListsAndRecursion-5

次の関数を、ライブラリやリスト内包表記を利用せずに実装しろ、と。

  • all?
  • each
  • filter
  • split
  • take

順番に行ってみよう。まずは all?

^o^ > iex practice_10_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.all?([true, true, true])
true
iex(2)> MyList.all?([true, false, true])
false

つぎに each

iex(3)> MyList.each([1, 2, 3], &IO.puts/1)
1
2
3
nil

nileach 自体の返り値かな。
つぎ、filter

iex(4)> MyList.filter([1, 2, 3, 4, 5], &(&1 > 2))
[3, 4, 5]

split

iex(5)> MyList.split([1, 2, 3, 4, 5], 2)
{[1, 2], [3, 4, 5]}

最後に take

iex(6)> MyList.take([1, 2, 3, 4, 5], 3)
[1, 2, 3]

Elixir 練習問題 ListsAndRecursion-4

^o^ > iex practice_7_4.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.span(3, 7)
[3, 4, 5, 6, 7]

mapreduce も使ってないな。

Elixir 練習問題 ListsAndRecursion-3

今度の練習問題はカエサル暗号だ。

^o^ > iex practice_7_3.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.caesar('ryvkve', 13)
'elixir'

Elixir 練習問題 ListsAndRecursion-2

^o^ > iex practice_7_2.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.max([1,2,3,4,5])
5
iex(2)> MyList.max([5,4,3,2,1])
5

Elixir 練習問題 ListsAndRecursion-1

^o^ > iex practice_7_1.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyList.mapsum([1, 2, 3], &(&1 * &1))
14

Elixir ではクロージャは作れない?

Elixir の関数は、関数を返すことができて、その関数は元の環境を覚えている。だからこないだのエントリでは「クロージャだ」と書いた。
だけど、今日になって違うんじゃないかと思うようになった。というのは、返ってきた関数は確かに元の環境を覚えているけど変更はできないみたいだからだ。
例えば、JavaScript で典型的なクロージャを書いてみよう。下の make_counter 関数の返す関数は、呼び出されるごとに 1 ずつ大きな数を返す。

^o^ > node counter.js
1
2
3

Elixir で同じように書いてみよう。

見てわかるように、JavaScript のコードをほぼそのまま Elixir で書き直したものだ。ところが、これを実行してみると:

^o^ > elixir counter.exs
1
1
1

このとおり、関数を何度呼び出しても数が増えていかない。
これって、やっぱりクロージャとは言わないんじゃ?それとも何か間違ってる?

Elixir 練習問題 ModulesAndFunctions-6

今度のは一種の数あて問題だ。

^o^ > iex practice_6_6.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Chop.guess(273, 1..1000)
It is 500
It is 250
It is 375
It is 312
It is 281
It is 265
It is 273
273
:ok

あれ、関数の戻り値が表示されちゃうな。まあ、いいか。