LoginSignup
0
0

More than 5 years have passed since last update.

Kuinでクロージャ

Posted at

クロージャは関数を拡張した概念で、環境(スコープのようなもの)を持った関数のことです。と言っても関数型言語に触った人間でなければなかなか分かりづらい概念だと思います。

Wikipedia - クロージャ

Java言語などではクロージャはクラスで実装されています。これに習ってクラスを使ってクロージャを作ってみましょう。

足し合わせを行うクロージャ

まずは、決められた数を足し合わせるクロージャです。

increment.kn
; クロージャのインターフェース
class ClosureIntToInt()
    +func body(n: int): int
        ret 0
    end func
end class

; クロージャを生成する関数
func increment(delta: int): @ClosureIntToInt
    class Increment(@ClosureIntToInt)
        +var delta1: int
        +*func body(n: int): int
            ret n + me.delta1
        end func
    end class

    var res: Increment :: #Increment
    do res.delta1 :: delta
    ret res
end func

func main()
    var f: @ClosureIntToInt :: @increment(3)
    do dbg@print(f.body(1).toStr() ~ "\n")
    do dbg@print(f.body(3).toStr() ~ "\n")
    do dbg@print(f.body(5).toStr() ~ "\n")
end func

クロージャを生成する関数の外側にインターフェースを作るのがポイントです。Kuinにはインターフェースを作成する機能はないのでクラスで代用します。クロージャのメソッドを呼び出すことで計算を行います。

クロージャを生成する関数の中にクロージャクラスの定義を書きます。生成関数はクロージャクラスではなく、先ほどのインターフェースの参照を送出することでクロージャの実装を隠蔽します。具体的に言うと、@increment(3)で3を足し合わせるクロージャを生成するのですが、その値を保持するdelta1フィールドにはアクセスすることができません。なぜならば、increment関数の外側でIncrementクラスを指定することができないからです。試しにmain関数内にdo dbg@print((f $ @Increment).delta1)と記述するとコンパイルエラーになります。

クロージャによってイミュータブル(immutable)なオブジェクトを生成することができます。イミュータブルは「書き換え不能な」という意味です。Kuinでもイミュータブルなオブジェクトを作ることは可能なのです。

カウントを行うクロージャ

次に、カウントを行うクロージャです。

counter.kn
; クロージャのインターフェース
class ClosureVoidToInt()
    +func body(): int
        ret 0
    end func
end class

; クロージャを生成する関数
func counter(): @ClosureVoidToInt
    class Counter(@ClosureVoidToInt)
        +var cnt: int
        +*func body(): int
            do me.cnt :+ 1
            ret me.cnt
        end func
    end class

    var res: Counter :: #Counter
    do res.cnt :: 0
    ret res
end func

func main()
    var f: @ClosureVoidToInt :: @counter()
    do dbg@print(f.body().toStr() ~ "\n")
    do dbg@print(f.body().toStr() ~ "\n")
    do dbg@print(f.body().toStr() ~ "\n")
end func

プログラムを実行して結果を確認してみましょう。クロージャを呼び出すたびにカウント値が1つずつ増えていきます。

結論

Kuin言語でもクロージャを生成することが可能であることが分かりました。また、Kuinの入れ子構造と継承機能を使えばファイルスコープを使わなくともイミュータブルなオブジェクトを作ったりカプセル化を行うことが可能であることが分かりました。

0
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
0
0