Nao000のぶろぐ

蝶を追っている少年になりたい

「第一級関数」というのを見ていく

はじめに

「第一級関数」というのは性質のことを意味するらしい。Microsoft によると以下の基準があるとのこと。

ファースト クラスのステータスの標準的な基準は次のとおりです。

  • 関数を識別子にバインドすることはできますか。 つまり、名前を付けることができますか。
  • 関数をリストなどのデータ構造に格納できますか。
  • 関数呼び出しの引数として関数を渡すことはできますか。
  • 関数呼び出しから関数を返すことはできますか。

https://docs.microsoft.com/ja-jp/dotnet/fsharp/introduction-to-functional-programming/first-class-functions

Elixirで試してみる。この性質を持っているかは分かりませんが、関数型なので恐らく持っているでしょう。 カリー化の勉強中なので関数名や変数名が Curry だったりします。

使うモジュール

    defmodule Curry do
        def add(x,y) do
            x+y
        end

        def cadd(x) do
            fn y -> add(x,y) end
        end

        def callFunction(f) do
            f.()
        end
    end

1つ1つ「多分こういうことだろう」というのを見ていく

関数を識別子にバインドすることはできますか

    iex(20)> crry = Curry.cadd(10)
    #Function<0.54427309/1 in Curry.cadd/1>
    iex(21)> crry.(20)
    30
    iex(22)>

できてる。

関数をリストなどのデータ構造に格納できますか。

    iex(15)> crry1 = Curry.cadd(1000)
    #Function<0.54427309/1 in Curry.cadd/1>
    iex(16)> crry2 = Curry.cadd(2000)
    #Function<0.54427309/1 in Curry.cadd/1>
    iex(17)> crry3 = Curry.cadd(3000)
    #Function<0.54427309/1 in Curry.cadd/1>
    iex(18)> sample = [crry1, c]
    c/1           c/2           case/2        cd/1          ceil/1
    clear/0       cond/1        continue/0    crry          crry1
    crry2         crry3
    iex(18)> sample = [crry1, crry2, crry3]
    [#Function<0.54427309/1 in Curry.cadd/1>,
     #Function<0.54427309/1 in Curry.cadd/1>,
     #Function<0.54427309/1 in Curry.cadd/1>]
    iex(19)>

できてる。

関数呼び出しの引数として関数を渡すことはできますか。

以下のように実行する。確かに関数の引数に関数を渡せています。

    /home/trial # iex curry.ex
    Erlang/OTP 21 [erts-10.3.5.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]

    Interactive Elixir (1.8.1) - press Ctrl+C to exit (type h() ENTER for help)
    iex(1)> myFunc = fn -> "Hello World" end
    #Function<20.128620087/0 in :erl_eval.expr/5>
    iex(2)> Curry.callFunction(myFunc)
    "Hello World"
    iex(3)>

関数呼び出しから関数を返すことはできますか。

これは 1. で書いたカリー化の実装と同じでは・・・?

再掲

    iex(20)> crry = Curry.cadd(10)
    #Function<0.54427309/1 in Curry.cadd/1>
    iex(21)> crry.(20)
    30
    iex(22)>

確かに 変数crry に無名関数を返しています。