Elixir 練習問題 ModulesAndFunctions-6

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

defmodule Chop do

  def guess(actual, a..b) do
    g = div(a + b, 2)
    _guess(actual, a..b, g)
  end

  def _guess(actual, _, g) when actual == g do
    IO.puts("It is " <> to_string(g))
    IO.puts(g)
  end
  def _guess(actual, a.._, g) when actual < g do
    IO.puts("It is " <> to_string(g))
    guess(actual, a..(g - 1))
  end
  def _guess(actual, _..b, g) do
    IO.puts("It is " <> to_string(g))
    guess(actual, (g + 1)..b)
  end

end
^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

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

Elixir 練習問題 ModulesAndFunctions-1~3

まずは、本の説明に出てきた Time モジュールに triple 関数を追加。

defmodule Times do

  def doubles(n) do
    n * 2
  end

  def triple(n) do
    n * 3
  end

end

そしてこれを2つのやり方で実行。1つは iex の引数として読み込んで実行する。

^o^ > iex practice_6_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)> Times.triple(2)
6

もう1つのやり方は、iex の中で c コマンドを使ってファイルをコンパイルして読み込む。

^o^ > iex
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c "practice_6_1.exs"
[Times]
iex(2)> Times.triple(2)
6

こっちのやり方だと、モジュールをコンパイルした Elixir.Times.beam ファイルができるんだな。

最後に、Time モジュールに quadruple 関数を追加。

defmodule Times do

  def doubles(n) do
    n * 2
  end

  def triple(n) do
    n * 3
  end

  def quadruple(n) do
    doubles(n) * doubles(n)
  end

end

実行してみる。

^o^ > iex practice_6_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)> Times.quadruple(2)
16

Elixir 練習問題 Functions-4

Elixir では、関数を返す関数を書くことができる。しかも、返ってくる関数はそれが定義された元の環境を覚えている。つまりクロージャだ。
というわけで、練習問題をやってみよう。

iex(1)> prefix = fn a -> (fn b -> a <> " " <> b end) end
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(2)> mrs = prefix.("Mrs")
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(3)> mrs.("Smith")
"Mrs Smith"
iex(4)> prefix.("Elixir").("Rocks")
"Elixir Rocks"

Elixir 練習問題 Functions-3

iex(1)> fizzbuzz = fn
...(1)>   0, 0, _ -> "FizzBuzz"
...(1)>   0, _, _ -> "Fizz"
...(1)>   _, 0, _ -> "Buzz"
...(1)>   _, _, n -> n
...(1)> end
#Function<18.52032458/3 in :erl_eval.expr/5>
iex(6)> fizzbuzz2 = fn n -> fizzbuzz.(rem(n, 3), rem(n, 5), n) end
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(7)> fizzbuzz2.(10)
"Buzz"
iex(8)> fizzbuzz2.(11)
11
iex(9)> fizzbuzz2.(12)
"Fizz"
iex(10)> fizzbuzz2.(13)
13
iex(11)> fizzbuzz2.(14)
14
iex(12)> fizzbuzz2.(15)
"FizzBuzz"
iex(13)> fizzbuzz2.(16)
16

Elixir 練習問題 Functions-1

「プログラミングElixir」、第I部を読み終わった。これから少しずつアウトプットしていこう。
とりあえずは、第5章 無名関数 の練習問題から、関数を3つ(list_concat, sum, pair_tuple_to_list)作れ、と。

まずは list_concat

iex(1)> list_concat = fn l1, l2 -> l1 ++ l2 end
#Function<12.52032458/2 in :erl_eval.expr/5>
iex(2)> list_concat.([:a, :b], [:c, :d])
[:a, :b, :c, :d]

次に sum

iex(3)> sum = fn a, b, c -> a + b + c end
#Function<18.52032458/3 in :erl_eval.expr/5>
iex(4)> sum.(1, 2, 3)
6

最後に pair_tuple_to_list

iex(5)> pair_tuple_to_list = fn {a, b} -> [a, b] end
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(6)> pair_tuple_to_list.( {1234, 5678} )
[1234, 5678]

本買った

 cf. 20 次にどこへ行こう – Where to go next – Elixir

さて、今年ももうすぐ終わりだ。
12月の初めから1月弱をかけて Elixir のチュートリアル(GETTING STARTED)をやってきたわけだけども、Ruby 風の文法の中に Haskell のようなパターンマッチングがあったりと結構面白い言語だと思った。特にパイプ演算子(|>)で関数を数珠つなぎにしてデータを流していくところなんか、Haskell にもなく、新鮮に感じた。

というわけで、本を買った。来年はこれをやるぞ!

[amazonjs asin=”4274219151″ locale=”JP” title=”プログラミングElixir”]