ブロックを表現

関数型言語Cleanでは、以下のように、局所的な関数を定義できる。

関数定義 where [局所関数定義]


Cleanの

// Clean
add_square a b = a2 + b2
  where
    a2 = a*a
    b2 = b*b

は、Pythonでは以下のように表現できる。

>>> lambda a, b: [a2+b2
...   for a2 in [a*a]
...   for b2 in [b*b]
... ][0]
<function <lambda> at 0x00E5A970>
>>> _(1, 2)
5

Cleanでwhereはネストできる。

// Clean
add_square a b = c
  where
    c = a2 + b2
      where
        a2 = a*a
        b2 = b*b

Pythonでは、以下のようにネスト可能。

>>> lambda a, b: [c
...   for c in [a2+b2 for a2 in [a*a] for b2 in [b*b]]
... ][0]
<function <lambda> at 0x00E5A970>
>>> _(1, 2)
5

これを並列に並べると以下のようになる。

>>> lambda a, b: [c
...   for a2 in [a*a]
...   for b2 in [b*b]
...   for c in [a2+b2]
... ][0]
<function <lambda> at 0x00E5A970>
>>> _(1, 2)
5

一般的に、{式1, 式2, ..., 式n} で値として式nを持つブロックは、以下のように表現できる。上記の例のように、inの後の式でネストしても、forをフラットに並べても読みやすい方をとれば良い。また、ガードはifで表現する。

[(式1, 式2, ..., 式n,)
  for ローカル変数1 in [式] iffor ローカル変数2 in [式] if 式
  ...
][0][-1]

パラメータを付けたい、もしくは遅延評価したい場合、以下のようにlambda式にする。
{|引数1, 引数2, ...| 式1, 式2, ..., 式n}
を表現すると以下の通り。

lambda 引数1, 引数2, ...: [(式1, 式2, ..., 式n,)
  for ローカル変数1 in [式] iffor ローカル変数2 in [式] if 式
  ...
][0][-1]


追記(2008/3/16):

ifの意味は、関数型言語のガードとちょっと意味が違うかも。もう少し考えるつもり。