とりあえず一通り読み終わった。けど、第II部の並行プログラミング以降はかなり消化不良。特にマクロのあたりなんかはほとんどついていけなかった。
まあ、いい。今年はまだ10カ月以上ある。少しずつやっていこう。
[amazonjs asin=”4274219151″ locale=”JP” title=”プログラミングElixir”]
takatoh's blog – Learning programming languages.
とりあえず一通り読み終わった。けど、第II部の並行プログラミング以降はかなり消化不良。特にマクロのあたりなんかはほとんどついていけなかった。
まあ、いい。今年はまだ10カ月以上ある。少しずつやっていこう。
[amazonjs asin=”4274219151″ locale=”JP” title=”プログラミングElixir”]
defmodule ASCII do def is_printable(charlist) do charlist |> Enum.map(&printable?/1) |> Enum.all? end defp printable?(c) do (32 <= c) and (c <= 126) end end
^o^ > iex practice_11_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)> ASCII.is_printable('hello') true iex(2)> ASCII.is_printable('hello\n') false
defmodule Order do def sales_tax(orders, tax_rates) do orders |> Enum.map(fn o -> {o, tax_rate(o, tax_rates)} end) |> Enum.map(fn {o, tax_rate} -> Keyword.put(o, :total_amount, add_tax(o, tax_rate)) end) end defp tax_rate(order, rates) do ship_to = Keyword.get(order, :ship_to) Keyword.get(rates, ship_to, 0.0) end defp add_tax(order, tax_rate) do Keyword.get(order, :net_amount) * (1.0 + tax_rate) end end tax_rates = [ NC: 0.075, TX: 0.08 ] orders = [ [ id: 123, ship_to: :NC, net_amount: 100.00 ], [ id: 124, ship_to: :OK, net_amount: 35.50 ], [ id: 125, ship_to: :TX, net_amount: 24.00 ], [ id: 126, ship_to: :TX, net_amount: 44.80 ], [ id: 127, ship_to: :NC, net_amount: 25.00 ], [ id: 128, ship_to: :MA, net_amount: 10.00 ], [ id: 129, ship_to: :CA, net_amount: 100.00 ], [ id: 130, ship_to: :NC, net_amount: 50.00 ] ] Order.sales_tax(orders, tax_rates) |> Enum.each(&IO.inspect/1)
^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 が最初に追加されちゃってるのがちょっと気に入らないけど、まあいいか。
以前に作った span
関数と内包表記を使って 2 から n までの素数。
defmodule MyList do def span(from, to) when from == to, do: [to] def span(from, to), do: [from | span(from + 1, to)] def primes(n) do for x <- span(2, n), is_prime(x), do: x end defp is_prime(2), do: true defp is_prime(3), do: true defp is_prime(n) do m = div(n, 2) Enum.all?(Enum.map(span(2, m), fn x -> rem(n, x) != 0 end)) end end
^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]
flattenn
。
defmodule MyList do def flatten(list) do _flatten(list, []) end defp _flatten([], r) do Enum.reverse(r) end defp _flatten([head|tail], r) do if is_list(head) do _flatten(tail, Enum.reverse(flatten(head)) ++ r) else _flatten(tail, [head | r]) end end end
^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]
sudo userdel
コマンドを使う。
takatoh@apostrophe $ sudo userdel -r sombrero [sudo] password for takatoh: userdel: sombrero のメールスプール (/var/mail/sombrero) がありません
-r
はホームディレクトリとメールスプールも削除するオプション。
次の関数を、ライブラリやリスト内包表記を利用せずに実装しろ、と。
defmodule MyList do def all?([]), do: true def all?([head | tail]) when head, do: all?(tail) def all?(_list), do: false def each([], _func) do end def each([head|tail], func) do func.(head) each(tail, func) end def filter([], _prod) do [] end def filter([head|tail], prod) do if prod.(head) do [head | filter(tail, prod)] else filter(tail, prod) end end def split(list, n), do: _split({[], list}, n) defp _split(result, 0), do: result defp _split(result = {_left, []}, _), do: result defp _split({left, [head|tail]}, n), do: _split({left ++ [head], tail}, n - 1) def take(list, n) do {result, _} = split(list, n) result end end
順番に行ってみよう。まずは 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
nil
は each
自体の返り値かな。
つぎ、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]
defmodule MyList do def map([], _func), do: [] def map([head|tail], func), do: [func.(head) | map(tail, func)] def reduce([], value, _func) do value end def reduce([head|tail], value, func) do reduce(tail, func.(head, value), func) end def span(from, to) when from == to, do: [to] def span(from, to), do: [from | span(from + 1, to)] end
^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]
map
も reduce
も使ってないな。
今度の練習問題はカエサル暗号だ。
defmodule MyList do def map([], _func), do: [] def map([head|tail], func), do: [func.(head) | map(tail, func)] def reduce([], value, _func) do value end def reduce([head|tail], value, func) do reduce(tail, func.(head, value), func) end def caesar(list, n) do map(list, fn c -> rem(c + n - ?a, 26) + ?a end) end end
^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'
defmodule MyList do def reduce([], value, _func) do value end def reduce([head|tail], value, func) do reduce(tail, func.(head, value), func) end def max([head|tail]) do reduce(tail, head, &_max/2) end defp _max(a, b) when a < b, do: b defp _max(a, _), do: a end
^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