LoginSignup
14
1

More than 1 year has passed since last update.

&>=/2, &<=/2, &</2などなどはFunction capturingです(Elixir)

Last updated at Posted at 2022-03-20

山里は冬ぞ寂しさまさりける人目も草もかれぬと思へば

Advent Calendar 2022 78日目1の記事です。
I'm looking forward to 12/25,2022 :santa::santa_tone1::santa_tone2::santa_tone3::santa_tone4::santa_tone5:
私のAdvent Calendar 2022 一覧


はじめに

Elixirを楽しんでいますか:bangbang::bangbang::bangbang:

&>=/2, &<=/2, &</2などは、Function capturingです。
という話を書きます。

&>=/2, &<=/2, &</2

&>=/2, &<=/2, &</2はそれぞれ、enumerableなものから最大値、最小値を取得する関数の第3引数sorterのデフォルト値に指定されています。

第3引数sorterのデフォルト 関数
&>=/2 Enum.max/3
&>=/2 Enum.max_by/4
&<=/2 Enum.min/3
&<=/2 Enum.min_by/4
&</2 Enum.min_max_by/4

たとえば、Enum.max/3をみてみましょう。

スクリーンショット 2022-03-21 2.00.59.png

一見するとわかりにくいかもしれません。
引数をそれぞれ詳しくみていきます。

  • 第1引数 enumerable
  • 第2引数 sorter: デフォルト値は、&>=/2 ※意味は後述
  • 第3引数 empty_fallback: デフォルト値は、fn -> raise Enum.EmptyError endという引数0個の無名関数

とみます。
な〜んてことない人は、相当なAlchemistです。
つまり、この説明を読んでな〜んてことない人になったあなたはAlchemistです。

What's /2 ?

/2というのは引数が2つという意味です。
/0だと引数が0。
/1だと引数が1。

専門家の間では、arity(アリティ)と呼ばれます。

>=/2

>=/2を深掘りしてみます。
>=/2の内部実装は以下の通りです。

  @doc guard: true
  @spec term >= term :: boolean
  def left >= right do
    :erlang.>=(left, right)
  end

2つの引数を:erlang.>=/2に渡して呼び出しています。

こんな書き方(呼び出し方)はしなくてよいのですが、紹介だけしておくとKernel.>=(4, 3)と書けます。

他も気になる方は、ドキュメント</>を迷わず押してみてください。
ソースコードにジャンプできます。

&>=/2, &<=/2, &</2などは、Function capturing

&>=/2, &<=/2, &</2などは、Function capturingです。

&>=/2を実行した結果と、fn a, b -> a >= b endを実行した結果は同じです。

iex> fc = (&>=/2) 
&:erlang.>=/2

iex> f = fn a, b -> a >= b end
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> fc.(3, 1)
true

iex> f.(3, 1)
true

iex> fc.(3, 4)
false

iex> f.(3, 4)
false

fn a, b -> a >= b endを&記法で書くと、& &1 >= &2となります。
もうここまで来ちゃうと

iex> (&>=/2) == (& &1 >= &2)
true

と、(&>=/2) == (& &1 >= &2)trueとして成立します。

公式ドキュメントは、以下をご参照ください。

その他

何に使うかはこの際、考えません。
以下のようなものを作ることができます。
ソースコード中ではじめてみると、なんだこれ? となること請け合いです。

iex> &+/2
&:erlang.+/2

iex> &-/2
&:erlang.-/2

iex> &++/2
&:erlang.++/2

iex> &<>/2
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> &../2
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> &**/2
&Kernel.**/2

iex> &=/2 
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> &==/2
&:erlang.==/2

iex> & &&/2
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> &!/1
#Function<44.65746770/1 in :erl_eval.expr/5>

iex> &in/2 
#Function<43.65746770/2 in :erl_eval.expr/5>

iex> &**/2 
&Kernel.**/2

Wrapping up :lgtm::lgtm::lgtm::lgtm::lgtm:

&>=/2, &<=/2, &</2などは、Function capturingです。

Enjoy Elixir:bangbang::bangbang::bangbang:
$\huge{Enjoy\ Elixir🚀}$

以上です。

尚々書

先日書いた「Enum.max_by/4 を説明します(Elixir)」の中でもこの記事の内容は一部触れています。
Enum.max_by/4は案外奥が深く、内容が盛り沢山になりました。
&>=/2, &<=/2, &</2は初見殺し感が満載なので、これらに絞って記事を書き起こしました。


I organize autoracex.
And I take part in NervesJP, fukuoka.ex, EDI, tokyo.ex, Pelemay.
I hope someday you'll join us.

We Are The Alchemists, my friends!

  1. @kaizen_nagoya さんの「「@e99h2121 アドベントカレンダーではありますまいか Advent Calendar 2020」の改訂版ではありますまいか Advent Calendar 2022 1日目 Most Breakthrough Generator」から着想を得て、模倣いたしました。

14
1
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
14
1