undefined

bokuweb.me

ElixirですごいE本 3章


3章

すごいErlangゆかいに学ぼう!

すごいErlangゆかいに学ぼう!

3.1 パターンマッチ

defmodule Test do
  def greet(:male, name), do: IO.puts "Hello, Mr.#{name}!" 
  def greet(:female, name), do: IO.puts "Hello, Mrs.#{name}!"
  def greet(_, name), do: IO.puts "Hello, #{name}!"
end

Test.greet :male, "Jack"
Test.greet :female, "Betty"
Test.greet :foo, "bar"

http://play.elixirbyexample.com/s/efd791c8ab

ちょっとこったパターンマッチ

defmodule Functions do
  def head([h|_]), do: h
  def second([_,x|_]), do: x
end

IO.puts Functions.head [1,2,3,4]
IO.puts Functions.second [1,2,3,4]

http://play.elixirbyexample.com/s/439c796408

束縛する変数

  • パターンマッチの一つ限界
  • 問題解決としてガードを使う
defmodule Functions do
  def valid_time({date={y,m,d}, time={h,min,s}}) do
    IO.puts "The Date tuple #{inspect date} says today is: #{y}/#{m}/#{d}"
    IO.puts "The time tuple #{inspect time} indicates: #{h}:#{min}:#{s}"
  end

  def valid_time(_), do: IO.puts "Stop feeding me wrong data!"
end

IO.puts Functions.valid_time({{2013,12,12},{09,04,43}})
IO.puts Functions.valid_time({{2013,12,12},{09,04}})

http://play.elixirbyexample.com/s/e26faf7eaf

3.2 ガードだ、ガード

  • ガード式の基本的なルールは成功時にtrueを返す
  • ガード式には数学的な演算やデータ型に対する関数(is_atom/1など)が使えるが、ユーザ定義の関数を受けいれない

ErlangVMではガードで使える式に制限があります:

  • 比較演算子(==,!=,===,!==,>,<,<=,>=)
  • 論理演算子(and,or)と否定演算子(not,!)
  • 算術演算子(+,-,*,/)
  • 左側がリテラルの場合の<>と++
  • in演算子
    以下の全ての型チェック関数:
  • is_atom/1
  • is_binary/1
  • is_bitstring/1
  • is_boolean/1
  • is_float/1
  • is_function/1
  • is_function/2
  • is_integer/1
  • is_list/1
  • is_map/1
  • is_number/1
  • is_pid/1
  • is_port/1
  • is_reference/1
  • is_tuple/1
    それに加えてこれらの関数:
  • abs(number)
  • bit_size(bitstring)
  • byte_size(bitstring)
  • div(integer, integer)
  • elem(tuple, n)
  • hd(list)
  • length(list)
  • map_size(map)
  • node()
  • node(pid | ref | port)
  • rem(integer, integer)
  • round(number)
  • self()
  • tl(list)
  • trunc(number)
  • tuple_size(tuple)

5 case,condそしてif - case, cond and if - Elixir

defmodule Functions do
  def right_age(x) when x >= 16 and x <= 104, do: true
  def right_age(_), do: false
    
  def wrong_age(x) when x < 16 or x > 104, do: true
  def wrong_age(_), do: false
end

IO.puts Functions.right_age 20
IO.puts Functions.right_age 105
IO.puts Functions.right_age 14

IO.puts Functions.wrong_age 20
IO.puts Functions.wrong_age 105
IO.puts Functions.wrong_age 14

http://play.elixirbyexample.com/s/b719f280b4

3.3 ifってなんだ?!

  • Elixirではマッチしなくてもエラーとならない
defmodule What_the_if do
  def oh_god(n) do
    if n === 2 do
      :might_succeed
    else
      :always_does
    end
  end
end

IO.puts What_the_if.oh_god 2
IO.puts What_the_if.oh_god 1

http://play.elixirbyexample.com/s/bf319b9d04

複数のガードを使う場合はcaseがいいっぽい。

defmodule What_the_if do
  def help_me(animal) do
    talk = case animal do
      :cat  -> "meow"
      :beef -> "mooo"
      :dog  -> "bark"
      :tree -> "bark"
      _     -> "fgdadfgna"
    end
    "#{animal}, sys #{talk}!"
  end
end

IO.puts What_the_if.help_me :cat
IO.puts What_the_if.help_me :beef
IO.puts What_the_if.help_me :dog
IO.puts What_the_if.help_me :tree
IO.puts What_the_if.help_me :foo

http://play.elixirbyexample.com/s/6e33bf967c

3.4 もしも・・の場合

defmodule What_the_if do
  def beach(temperature) do
    case temperature do
      {:celsius, n} when n >= 20 and n <= 45 -> "favorable"
      {:kelvin, n} when n >= 293 and n <= 318 -> "scientifically favorite"
      {:fahrenheit, n} when n >= 68 and n <= 113 -> "favorite in the US"
      _ -> "avoid beach"
    end
  end
end


IO.puts What_the_if.beach {:celsius, 40}
IO.puts What_the_if.beach {:celsius, 46}
IO.puts What_the_if.beach {:kelvin, 294}
IO.puts What_the_if.beach {:kelvin, 319}
IO.puts What_the_if.beach {:fahrenheit, 69}
IO.puts What_the_if.beach {:fahrenheit, 114}

http://play.elixirbyexample.com/s/3b94d571cb

他にもcondがある。

5 case,condそしてif - case, cond and if - Elixir

iex> cond do
...>   2 + 2 == 5 ->
...>     "This will not be true"
...>   2 * 2 == 3 ->
...>     "Nor this"
...>   1 + 1 == 2 ->
...>     "But this will"
...> end
"But this will"

これは命令型言語のelse if句と同じです(それらより使う機会は少ないですが).