Giả sử tôi có một đóng cửa vườn đa dạng như xương trần mẫu này:Làm cách nào để đóng cửa tự giới thiệu?
(let ((alpha 0) #| etc. |#)
(lambda()
(incf alpha)
#| more code here |#
alpha))
Giả sử tôi (funcall)
một ví dụ về điều đó đóng cửa ba lần, và ở giữa việc thực hiện thứ ba, việc đóng cửa này muốn cứu bản thân một nơi nào đó (trong một bảng băm, nói). Sau đó, tôi không (funcall)
trường hợp này trong một thời gian. Sau đó, tôi lấy trường hợp này từ bảng băm và (funcall)
một lần nữa, nhận giá trị trả lại là 4.
Chức năng trong bao đóng tham chiếu đến chính nó, để nó có thể tự lưu trong bảng băm đó?
EDIT 1: Dưới đây là ví dụ chi tiết hơn. Tôi hoàn thành mục tiêu bằng cách vượt qua việc đóng cửa cho chính nó như là một tham số. Nhưng tôi muốn đóng cửa tự mình làm tất cả những điều này mà không bị tự tham số hóa.
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: Vâng, tôi biết tôi có thể sử dụng một macro để trượt tên của các chức năng trong như tham số đầu tiên của nó, và sau đó sử dụng macro rằng thay vì (funcall)
, nhưng tôi vẫn muốn biết làm thế nào để cho một đóng cửa đề cập đến trường hợp riêng của nó.
EDIT 3: Để trả lời đề xuất loại SK-logic, tôi đã làm như sau, nhưng nó không làm những gì tôi muốn. Nó đẩy ba đóng mới vào ngăn xếp, không phải ba tham chiếu đến cùng một đóng. Xem cách khi tôi bật những người đó ra khỏi ngăn xếp, giá trị của các cuộc gọi là 1, 1 và 1 thay vì 6, 7 và 8?
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
CHỈNH SỬA 4: Đề xuất của Jon O đánh dấu chính xác. Dưới đây là các mã và đầu ra:
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: đề nghị Miron cũng đánh dấu, và thực sự làm cho mã một chút dễ đọc hơn:
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
Tôi giả định bằng cách "đóng" nghĩa là "chức năng ẩn danh". Trong mọi trường hợp, tôi không hiểu tại sao bạn không chỉ đơn giản là đặt tên cho nó? – delnan
Tôi không muốn một trường hợp mới đóng cửa. Tôi muốn cái cũ, với những thay đổi liên tục đến các biến kèm theo. Trong thực tế, có thể có một số trường hợp, mỗi trường hợp nên được muối đi đâu đó. Tất cả điều này có thể được thực hiện khi đặt tên cho nó không? Cú pháp sẽ là gì? –
Tôi không nói lisp rất tốt, nhưng tôi cho rằng một cái gì đó giống như "biểu thức chức năng tự thực hiện" phổ biến trong JavaScript sẽ làm các trick. – delnan