このベアボーンサンプルのような庭の種類のクロージャーがあるとします。
(let ((alpha 0) #| etc. |# )
(lambda ()
(incf alpha)
#| more code here |#
alpha))
そのクロージャ(funcall)
のインスタンスを3回実行し、3回目の実行の途中で、このクロージャが自分自身をどこかに保存したいとします(たとえば、ハッシュテーブル内)。(funcall)
それから私はしばらくの間このインスタンスをしません。次に、このインスタンスをハッシュテーブルと(funcall)
それから再度取得し、戻り値4を取得します。
クロージャー内の関数はどのようにそれ自体を参照するので、そのハッシュテーブルにそれ自体を保存できますか?
編集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
編集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
編集4:JonOの提案は正確に的を射た。コードと出力は次のとおりです。
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
編集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