はじめに
-
私は、Elixirの関数やifを1行で書くときに
,
を忘れがちです - 私は、Enum.reduce/3のfunのaccが1番目だったか2番目だったかを忘れがちです
- Twitterにぶつぶつつぶやいたことをまとめておきます
- kokura.ex#4:Elixirもくもく会~入門もあるよ(19:00) 参加中にまとめました
$ elixir -v
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Elixir 1.9.4 (compiled with Erlang/OTP 22)
if
if false do
:this
else
:that
end
- ↑これを1行で書こうとすると
if false, do: :this, else: :that
- これが正解です
- が、私は
false
のうしろの,
を忘れがちです
iex> if false do: :this, else: :that
** (SyntaxError) iex:6: unexpected keyword: do:. In case you wanted to write a "do" expression, you must either use do-blocks or separate the keyword argument with comma. For example, you should either write:
if some_condition? do
:this
else
:that
end
or the equivalent construct:
if(some_condition?, do: :this, else: :that)
where "some_condition?" is the first argument and the second argument is a keyword list
- プログラミング Elixir には次のように書かれています
Elixirでは、ifと、その邪悪な双子であるunlessは、2つのパラメータを取る。条件と、do:、else:というキーワードリストだ。
- ここにはっきりそう答えが書いてありますが、キーワードリストというのを読み飛ばしていました
- いろいろあって改めてGUIDESを読んでいまして、Keyword listsを英語が苦手なのでよちよち読んでいて上で言っている意味がわかりました
iex> if(false, [{:do, :this}, {:else, :that}])
:that
- そういうことだったのね!
- if の一行表記は間違えないとおもいます!
関数の一行表記
defmodule Foo do
def bar do
:bar
end
end
- ↑これの
bar
を1行で書こうとすると
defmodule Foo do
def bar, do: :bar
end
- これが正解です
- 私は
bar
の後ろの,
を忘れがちです - これもifのときとだいたい話は同じです
defmodule Foo do
def(bar, [{:do, :bar}])
end
- 関数の一行表記は間違えないとおもいます!
- 参考: def/2
Enum.reduce/3
-
私は、いつも第3引数に指定する関数の引数が、どっちが
acc
だったかを迷います - 単なる私のこじつけですが、
&1
で書いたときに、&1
は繰り返されるものが1個ずつ入るので、1番めがitem
、余った2番めがacc
とおぼえました - 具体的にみてみましょう
&で書いた場合
iex> (
...> %{carol: 99, alice: 50, david: 40, bob: 60}
...> |> Enum.reduce([], &if(elem(&1, 1) >= 60, do: &2 ++ [elem(&1, 0)], else: &2))
...> )
[:bob, :carol]
iex> (
...> [1, 2, 3]
...> |> Enum.map(&(&1 * 2))
...> )
[2, 4, 6]
- 参考として、Enum.map/2も並べておきました
-
&1
には両方とも共通して、一個ずつ渡されるものが入っています
fnで書いた場合
iex> (
...> %{carol: 99, alice: 50, david: 40, bob: 60}
...> |> Enum.reduce([], fn {name, age}, acc -> if age >= 60, do: acc ++ [name], else: acc end)
...> )
[:bob, :carol]
iex> (
...> [1, 2, 3]
...> |> Enum.map(fn x -> x * 2 end)
...> )
[2, 4, 6]
- 1個ずつ渡されるものはfunの第一引数に入って、
acc
はfunの第二引数のほうに入ります!
おまけ
p [2, 3, 4, 5].reduce(0) {|acc, item| acc + item**2 } #=> 54