newLISP のクロージャ。。。または、破壊的関数の副作用

 newLISP でクロージャと言えば、コンテキストを思い浮かべますが、今回はちょっと違います。
 元ネタは、Closures and Contexts の “Stateful functions using self modifying code” から。

 先ずはスクリプトを、

(define (counter (x 1) reset-flag)
  (if-not reset-flag
      (++ 0 x)
    (counter (- x (counter)))))

 スクリプトのメインは、

(++ 0 x)

 です。0x の位置が逆では、と思われるかもしれませんが、ここがミソです。
 実際に動かしてみましょう。

> counter
(lambda ((x 1) reset-flag) 
 (if-not reset-flag 
  (inc 0 x) 
  (counter (- x (counter)))))
> (counter)
1
> (counter)
2
> (counter)
3
> (counter 5)
8
> (counter 0 true)
0
> (counter)
1
> counter
(lambda ((x 1) reset-flag) 
 (if-not reset-flag 
  (inc 1 x) 
  (counter (- x (counter)))))
> 

 予想通りの動作だったでしょうか?
 この動作に、先程の 0x の位置が重要になってきます。
 マニュアルでは、

inc

syntax: (inc place [num])

place の数値を 1.0 か オプションの数値 num 分加算し、結果を返します。inc は、浮動小数点数計算を実行し、渡された整数値を浮動小数点型に変換します。
Increments the number in place by 1.0 or by the optional number num and returns the result. inc performs float arithmetic and converts integer numbers passed into floating point type.<

place は、シンボルか、リスト構造内の位置、式によって返される数値のいずれかです。
place is either a symbol or a place in a list structure holding a
number, or a number returned by an expression.

 となっています。
 ++ ではなく inc ですが、違いは整数用( ++ )か浮動小数点用( inc )かだけです。
 ++inc も破壊的関数で、place の数値に num の数値を加算して、place の数値を置き換えます。
 そのため、上記スクリプトでは、スクリプト自体が書き換えられていく(!)訳です。つまり、破壊的関数の副作用を使ったクロージャ。

 以上、如何でしょうか?

No comments yet

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。