は、私は、この最低限のサンプルのようなありふれたクロージャがあるとします。クロージャーはどのようにしてクロージャーを参照できますか?
(let ((alpha 0) #| etc. |#)
(lambda()
(incf alpha)
#| more code here |#
alpha))
はI (funcall)
その閉鎖のインスタンス三回と仮定し、3回目の実行の途中で、この閉鎖は自分自身を保存したいですどこかで(ハッシュテーブルの中で)私はしばらくの間このインスタンス(funcall)
をしないでください。次に、ハッシュテーブルからこのインスタンスを取得し、戻り値が(funcall)
であるため、戻り値は4になります。
クロージャの関数は、それ自身を参照してそのハッシュテーブルに保存できますか?
EDIT 1:より詳細な例を示します。クロージャをパラメータとして渡して目標を達成します。しかし私はクロージャーが自己パラメータ化されずにすべてこれを自分自身にすることを望んでいます。
1 (defparameter *listeriosis* nil)
2 (defparameter *a*
3 (lambda()
4 (let ((count 0))
5 (lambda (param1 param2 param3 self)
6 (incf count)
7 (when (= 3 count)
8 (push self *listeriosis*)
9 (push self *listeriosis*)
10 (push self *listeriosis*))
11 count))))
12 (let ((bee (funcall *a*)))
13 (princ (funcall bee 1 2 3 bee)) (terpri)
14 (princ (funcall bee 1 2 3 bee)) (terpri)
15 (princ (funcall bee 1 2 3 bee)) (terpri)
16 (princ (funcall bee 1 2 3 bee)) (terpri)
17 (princ (funcall bee 1 2 3 bee)) (terpri))
18 (princ "///") (terpri)
19 (princ (funcall (pop *listeriosis*) 1 2 3 nil)) (terpri)
20 (princ (funcall (pop *listeriosis*) 1 2 3 nil)) (terpri)
21 (princ (funcall (pop *listeriosis*) 1 2 3 nil)) (terpri)
1
2
3
4
5
///
6
7
8
EDIT 2:はい、私はその最初のパラメータとして、関数の名前をスリップして、(funcall)
するのではなく、そのマクロを使用するためにマクロを使用することができます知っているが、私はまだどのように知りたいですクロージャーがそれ自身のインスタンスを参照できるようにします。
編集3:SK-Logicの種類の提案に応じて、私は以下のことをしましたが、私がしたいことはしません。スタック上に3つの新しいクロージャをプッシュし、同じクロージャに対する3つの参照をプッシュしません。スタックからそれらをポップすると、コールの値は6,7,8の代わりに1,1、そして1になります。
1 (defparameter *listeriosis* nil)
2 (defun Y (f)
3 ((lambda (x) (funcall x x))
4 (lambda (y)
5 (funcall f (lambda (&rest args)
6 (apply (funcall y y) args))))))
7 (defparameter *a*
8 (lambda (self)
9 (let ((count 0))
10 (lambda (param1 param2 param3)
11 (incf count)
12 (when (= 3 count)
13 (push self *listeriosis*)
14 (push self *listeriosis*)
15 (push self *listeriosis*))
16 count))))
17 (let ((bee (Y *a*)))
18 (princ (funcall bee 1 2 3 #| bee |#)) (terpri)
19 (princ (funcall bee 1 2 3 #| bee |#)) (terpri)
20 (princ (funcall bee 1 2 3 #| bee |#)) (terpri)
21 (princ (funcall bee 1 2 3 #| bee |#)) (terpri)
22 (princ (funcall bee 1 2 3 #| bee |#)) (terpri))
23 (princ "///") (terpri)
24 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
25 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
26 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
1
2
3
4
5
///
1
1
1
EDIT 4:Jon Oの提案が正確にマークに当たっています。ここでは、コードと出力です:
1 (defparameter *listeriosis* nil)
2 (defparameter *a*
3 (lambda()
4 (let ((count 0))
5 (labels ((self (param1 param2 param3)
6 (incf count)
7 (when (= 3 count)
8 (push (function self) *listeriosis*)
9 (push (function self) *listeriosis*)
10 (push (function self) *listeriosis*))
11 count))
12 (function self)))))
13 (let ((bee (funcall *a*)))
14 (princ (funcall bee 1 2 3)) (terpri)
15 (princ (funcall bee 1 2 3)) (terpri)
16 (princ (funcall bee 1 2 3)) (terpri)
17 (princ (funcall bee 1 2 3)) (terpri)
18 (princ (funcall bee 1 2 3)) (terpri))
19 (princ "///") (terpri)
20 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
21 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
22 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
1
2
3
4
5
///
6
7
8
EDIT 5:Miron氏の提案にもマークを打つ、そして実際にコードをもう少し読みやすくなります:
1 (defmacro alambda (parms &body body)
2 `(labels ((self ,parms ,@body))
3 #'self))
4 ;
5 (defparameter *listeriosis* nil)
6 (defparameter *a*
7 (lambda()
8 (let ((count 0))
9 (alambda (param1 param2 param3)
10 (incf count)
11 (when (= 3 count)
12 (push #'self *listeriosis*)
13 (push #'self *listeriosis*)
14 (push #'self *listeriosis*))
15 count))))
16 ;
17 (let ((bee (funcall *a*)))
18 (princ (funcall bee 1 2 3)) (terpri)
19 (princ (funcall bee 1 2 3)) (terpri)
20 (princ (funcall bee 1 2 3)) (terpri)
21 (princ (funcall bee 1 2 3)) (terpri)
22 (princ (funcall bee 1 2 3)) (terpri))
23 (princ "///") (terpri)
24 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
25 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
26 (princ (funcall (pop *listeriosis*) 1 2 3)) (terpri)
1
2
3
4
5
///
6
7
8
「クロージャ」とは、「匿名機能」を意味します。いずれにせよ、なぜあなたは単にそれに名前を付けるだけではないのか分かりません。 – delnan
私はクロージャーの新しいインスタンスを望んでいません。私は古い変数を囲み変数に続けて変更したい。実際には、いくつかのインスタンスが存在する可能性があります。インスタンスのそれぞれは、どこかで塩分を除去する必要があります。名前を付けてこれを行うことはできますか?構文は何でしょうか? –
私はlispをうまく話せませんが、JavaScriptでよく使われる「自己実行関数式」のようなものがこのトリックを行うと思います。 – delnan