「プログラミングElixir」を読み返しながら、例題の issues アプリを作ってるんだけど、なんかエラーが出てうまくいかない。
時間もあんまりとれないし、ああもう、めげそう…orz。
カテゴリー: Elixir
Elixir 練習問題 ControlFlow-3
こんな感じでいいかな。
defmodule OK do def ok!({:ok, data}), do: data def ok!(_), do: raise("Error occured.") end file = OK.ok! File.open("somefile")
^o^ > elixir practice_12_3.exs warning: variable file is unused practice_12_3.exs:6 ** (RuntimeError) Error occured. practice_12_3.exs:3: OK.ok!/1 (elixir) lib/code.ex:363: Code.require_file/2
ちなみに、somefile の代わりに存在するファイルで試してみると次のようになる。
^o^ > elixir practice_12_3.exs warning: variable file is unused practice_12_3.exs:6
エラーは起きない。警告が出てるのは file 変数を使ってないからだね。
Elixir 練習問題 ControlFlow-1
気が付けば前回の Elixir のエントリからひと月も経ってしまった。
ま、気を取り直して。FizzBuzz を case を使って書け、と。
defmodule FizzBuzz do def fizzbuzz(n) do case {rem(n, 3), rem(n, 5), n} do {0, 0, _} -> "FizzBuzz" {0, _, _} -> "Fizz" {_, 0, _} -> "Buzz" {_, _, m} -> to_string(m) end end end (1..20) |> Enum.each(&IO.puts(FizzBuzz.fizzbuzz(&1)))
^o^ > elixir practice_12_1.exs 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz
Elixir 練習問題 StringsAndBinaries-7
defmodule Sales do def csv_to_list(filename) do {:ok, file} = File.open(filename, [:read]) headers = (IO.read(file, :line) |> parse_csv_atom) IO.stream(file, :line) |> Enum.map(fn l -> parse_csv(l) end) |> Enum.map(fn sales -> Enum.zip(headers, sales) end) end defp parse_csv_atom(line) do String.trim(line, "\n") |> String.split(",") |> Enum.map(&String.to_atom/1) end defp parse_csv(line) do [id, ship_to, net_amount] = (String.trim(line, "\n") |> String.split(",")) [String.to_integer(id), String.to_atom(String.trim(ship_to, ":")), String.to_float(net_amount)] end end IO.inspect Sales.csv_to_list("sales.csv")
^o^ > cat sales.csv id,ship_to,net_amount 123,:NC,100.00 124,:OK,35.50 125,:TX,24.00 126,:TX,44.80 127,:NC,25.00 128,:MA,10.00 129,:CA,102.00 130,:NC,50.00 ^o^ > elixir practice_11_7.exs [[id: 123, ship_to: :NC, net_amount: 100.0], [id: 124, ship_to: :OK, net_amount: 35.5], [id: 125, ship_to: :TX, net_amount: 24.0], [id: 126, ship_to: :TX, net_amount: 44.8], [id: 127, ship_to: :NC, net_amount: 25.0], [id: 128, ship_to: :MA, net_amount: 10.0], [id: 129, ship_to: :CA, net_amount: 102.0], [id: 130, ship_to: :NC, net_amount: 50.0]]
Elixir 練習問題 StringsAndBinaries-6
defmodule Str do def capitalize(word) do String.to_charlist(word) |> to_upper([]) |> to_string end defp to_upper([], result) do Enum.reverse(result) end defp to_upper([32|tail], result) do to_upper(tail, [32|result]) end defp to_upper([?.|tail], result) do to_upper(tail, result) end defp to_upper([c|tail], result) do to_lower(tail, [upcase(c)|result]) end defp upcase(c) when c <= ?Z, do: c defp upcase(c), do: c - 32 defp to_lower([], result) do Enum.reverse(result) end defp to_lower([32|tail], result) do to_lower(tail, [32|result]) end defp to_lower([?.|tail], result) do to_upper(tail, [?.|result]) end defp to_lower([c|tail], result) do to_lower(tail, [lowcase(c)|result]) end defp lowcase(c) when c >= 97, do: c defp lowcase(c), do: c + 32 end IO.puts Str.capitalize("oh. a DOG. woof. ")
^o^ > elixir practice_11_6.exs Oh. A dog. Woof.
Elixir 練習問題 StringsAndBinaries-5
defmodule Str do def center(slist) do len = longest(slist) slist |> Enum.map(fn s -> _center(s, len) end) |> Enum.each(&IO.puts/1) end defp longest(slist) do slist |> Enum.map(&String.length/1) |> Enum.max end defp _center(str, len) do l = div(len - String.length(str), 2) String.duplicate(" ", l) <> str end end Str.center(["cat", "zebra", "elephant"])
^o^ > elixir practice_11_5.exs cat zebra elephant
Elixir 練習問題 StringsAndBinaries-4
defmodule Calculater do def calculate(charlist) do parse(charlist) |> calc end defp parse(charlist) do tokenize(charlist, [[]]) |> _parse end defp tokenize([], result) do Enum.reverse(result) end defp tokenize([32|tail], result) do tokenize(tail, [[] | result]) end defp tokenize([head|tail], [cur|rest]) do tokenize(tail, [cur ++ [head] | rest]) end defp _parse([opnd1, op, opnd2]) do num1 = number(opnd1, 0) num2 = number(opnd2, 0) {op, num1, num2} end defp number([], value) do value end defp number([digit|tail], value) do number(tail, value * 10 + digit - ?0) end defp calc({'+', n1, n2}), do: n1 + n2 defp calc({'-', n1, n2}), do: n1 - n2 defp calc({'*', n1, n2}), do: n1 * n2 defp calc({'/', n1, n2}), do: n1 / n2 end IO.puts Calculater.calculate('123 + 27') IO.puts Calculater.calculate('123 - 23') IO.puts Calculater.calculate('100 * 2') IO.puts Calculater.calculate('100 / 5')
^o^ > elixir practice_11_4.exs 150 100 200 20.0
Elixir 練習問題 StringsAndBinaries-3
ここのところ Ubuntu ばかりやっていたので、Elixir は久しぶり。
今日の練習問題は、['cat' | 'dog']
という式が、なぜ ['cat', 100, 111, 103]
になるのかという問題。まずは実際に確かめてみよう。
^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)> ['cat' | 'dog'] ['cat', 100, 111, 103]
まあ、答えは簡単だ。シングルクォートで囲まれた 'dog'
は実はただの整数のリストで、たまたまその整数すべてが文字コードとして解釈できるから 'dog'
になっているにすぎない。
iex(2)> [100, 111, 103] 'dog'
ところが、このリストの先頭に 'cat'
を追加してしまうと、すべてが文字コードとして解釈できる整数ではなくなってしまう。もう少し正確に言うと、リストの最初の要素がリスト、残りが整数になってしまっている。だから、後ろの3要素は文字ではなく文字コードで表示されている。
Elixir 練習問題 StringsAndBinaries-2
アナグラムの判定。パラメータがダブルクォートの文字列じゃなくて、シングルクォートの文字列なら簡単だ。シングルクォートの文字列はただのリストだから、ソートして比べればいい。
defmodule Anagram do def anagram?(word1, word2) do Enum.sort(word1) == Enum.sort(word2) end end
^o^ > iex practice_11_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)> Anagram.anagram?('hello', 'world') false iex(2)> Anagram.anagram?('hello', 'olleh') true
プログラミングElixir 読み終わった
とりあえず一通り読み終わった。けど、第II部の並行プログラミング以降はかなり消化不良。特にマクロのあたりなんかはほとんどついていけなかった。
まあ、いい。今年はまだ10カ月以上ある。少しずつやっていこう。
[amazonjs asin=”4274219151″ locale=”JP” title=”プログラミングElixir”]