LoginSignup
6
0

More than 3 years have passed since last update.

私は、Elixirの関数やifを1行で書くときに , を忘れがちだし、Enum.reduce/3のfunのaccが1番目だったか2番目だったかを忘れがち

Last updated at Posted at 2019-12-17

はじめに

$ 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では、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の第二引数のほうに入ります!

おまけ

  • Rubyの場合は、acc, itemの順ですよ
p [2, 3, 4, 5].reduce(0) {|acc, item| acc + item**2 }  #=> 54
6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0