お正月なのでカリー化しながらカリーを食べよう!

プログラミング

あけましておめでとうございます。本年も引き続きよろしくお願いいたします。

突然ですが,お正月らしいものを食べていますか?

おじさん,おばさん世代以上には懐かしく感じる「おせちもいいけど,カレーもね!」というCMがありました。

ということで,カリー化してみます。(もちろん,カリー化のカリーはカリーさんのカリーということ突っ込まなくてよいです。)

関数を戻り値とする関数

とりあえずすぐに使える環境がPythonなので,Pythonを使って書きますが一例として読んでください。

私が慣れていなくて普段使っていないのですが,関数の中で関数を定義することも,関数の戻り値として関数を返すことも,どちらもできます。

実際に書いてみたプログラムです。

def f(x):
    def g(y):
        return x * y
    return g

a = f(3)
b = f(20)
print(a(673))
print(b(101))
print(f(43)(47))

1行目から始まる関数fの定義の中で関数gを定義しています。

がんばれば,入れ子の入れ子の入れ子の・・・もできそうです。

さて,この関数f,gの戻り値はどうなるでしょうか。

5行目で,f(3)と関数fを呼び出しています。

1行目で仮引数x=1となります。

試しに1行目と2行目の間にprint(x)としてみると確認できます。

次に3行目からの関数gの定義になりますが,仮引数yは関数定義に用いる仮引数yのままです。

4行目のreturn x*yですが,x=3となっているので,関数gの戻り値(戻り式?)は 3*yとなります。

5行目で関数fの戻り値がreturn gとなっていますので,関数gの戻り値 3*yが戻り値になります。

その結果,戻り値が3*yである関数には,aという名前が割り当てられます。

同様に6行目では, 関数fの戻り値である20*yという関数に,bという名前が割り当てられます。

7行目の print(a(673)) では,aという名前が割り当てられた関数で実引数673が渡されます。

この673が仮引数yで受け取り,3*673を計算した2019が出力されます。

一応実行結果です。

2019
2020
2021

カリー化してみる

カリー化についてまとめようと思ったのですが,きっちり定義を区別しているサイトがあったのでリンクを貼っておきます。

とりあえず,2の定義を満たすように九九を表示するプログラムを書いてみます。

2. 「複数の引数を取る関数」を「一引数を取る関数のチェインに直す」こと

https://kazu-yamamoto.hatenablog.jp/entry/20110906/1315279311

7行目で「一引数を取る関数のチェイン」の形となっています。

def times(x):
    def times1(y):
        return x * y
    return times1

for i in range(1, 10):
    for j in range(1, 10):
        print(times(i)(j), end=' ')
    print()

実行結果です。

1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81

カリー化しているのに,高階関数に触れないのは少し微妙な気がしますが今回はこれでおしまいにします。

それではまた。

Posted by 春日井 優