Page List

Search on the blog

2010年12月25日土曜日

クロージャとは何か?(2)

前回に引き続き、クロージャについて。

前回のブログで、クロージャとは”汎用的な機能を持つ関数の機能を何らかの変数で固定して使うような仕組み”と説明しました。

実際に例を見て、クロージャとは何かを更に詳しく調べてみます。

1,2,3, ...., n
という数列の和を求める関数を書いてみます。
  1. def seriesSum(n):  
  2.   ret = 0  
  3.   for x in range(1, n+1):  
  4.       ret += x  
  5.   return ret  

久々のPython。。

では、次に、
1, 4, 9, ...., n^2
という数列の和を求める関数を書いてみましょう。
  1. def seriesSum(n):  
  2.   ret = 0  
  3.   for x in range(1, n+1):  
  4.       ret += x*x  
  5.   return ret  

じゃあ、一般的に
f(1), f(2), ..., f(n)
という数列の和を求める関数は書けないものでしょうか?

クロージャを使えば書けます。
こんな感じ。
  1. def genSeriesSum(_f):  
  2.   func = _f  
  3.   def seriesSum(n):  
  4.       ret = 0  
  5.       for x in range(1, n+1):  
  6.           ret += func(x)  
  7.       return ret  
  8.   return seriesSum  

使うときは、どうするのでしょうか?
例えば、fはx -> x^2の写像とする場合は以下のようにして使います。
  1. def square(x):  
  2.   return x*x  
  3.   
  4. squareSum = genSeriesSum(square)  
  5. print squareSum(10)  
では、説明してみます。
まず、genSeriesSum()について。
この関数は、
まず、関数オブジェクト_fを受け取ります。
そのあと、変数funcに_fを代入しています。
そして、関数内で定義された関数seriesSum()を関数オブジェクトとして返します。

ここでポイントは、seriesSum()の中のfuncという変数は、_fという値に固定されているということです。
つまり、genSeriesSum()は、機能を固定した(funcを_fにした)関数seriesSum()を生成するような関数であると言えます。
そう、これです。
「機能を固定した関数を生成する関数」
これが、クロージャです。

クロージャを使うと、こんなことも出来ます。
関数の微分値を求める関数。

  1. def genDeriverable(_f, _dx):  
  2.   f = _f  
  3.   dx = _dx  
  4.   def deriverable(x):  
  5.       return (f(x + dx) - f(x)) / dx  
  6.   
  7.   return deriverable  
どうでしょうか?
クロージャ、すごいです。
個人的には、クロージャとは、関数ファクトリーという感覚を覚えました。
私の認識が間違ってたら、是非是非指摘してくださいーー。

0 件のコメント:

コメントを投稿