znalazłem sposób przy użyciu kontynuacje mieć anonimowe lambdy nazywają siebie, a następnie przy użyciu makr rakieta do ukrycia składni dlatego uwagi anonimowy lambda wydaje się mieć "ja" operatora. Nie wiem, czy to rozwiązanie jest możliwe w innych wersjach Schematu, ponieważ zależy to od funkcji kontynuacji połączenia z kompozycją i Makro, aby ukryć składnię, używając parametrów składni.
Podstawowa idea jest taka, zilustrowana funkcją silni.
((lambda (n)
(call-with-values
(lambda() (call-with-composable-continuation
(lambda (k) (values k n))))
(lambda (k n)
(cond
[(= 0 n) 1]
[else (* n (k k (- n 1)))])))) 5)
Kontynuacja k jest wywołanie funkcji anonimowej silni, który trwa dwa argumenty, z których pierwszym jest sama kontynuacja. Tak więc, gdy w ciele wykonujemy (k k N), który jest równoważny z anonimową funkcją wywołującą samą siebie (w taki sam sposób, jak zrobiłaby to rekursywna o nazwie lambda).
Następnie ukrywamy podstawowy formularz za pomocą makra. Rakiety składni parametry umożliwiają transformację (self args ...) do (kk ARG ...)
więc możemy mieć:
((lambda-with-self (n)
(cond
[(= 0 n) 0]
[(= 1 n) 1]
[else (* n (self (- n 1)))])) 5)
Kompletny program rakieta to zrobić:
#lang racket
(require racket/stxparam) ;required for syntax-parameters
( define-syntax-parameter self (λ (stx) (raise-syntax-error #f "not in `lambda-with-self'" stx)))
(define-syntax-rule
(lambda-with-self (ARG ...) BODY ...)
(lambda (ARG ...)
(call-with-values
(lambda()(call/comp (lambda (k) (values k ARG ...))))
(lambda (k ARG ...)
(syntax-parameterize ([self (syntax-rules ()[(self ARG ...) (k k ARG ...)])])
BODY ...)))))
;Example using factorial function
((lambda-with-self (n)
(cond
[(= 0 n) 0]
[(= 1 n) 1]
[else (* n (self (- n 1)))])) 5)
To również odpowiada na moje poprzednie pytanie o różnice między różnymi rodzajami kontynuacji. Different kinds of continuations in Racket
ten działa tylko dlatego, że w przeciwieństwie do call-z-current-kontynuacja, call-z-sk-kontynuacja nie przerwie z powrotem do wiersza kontynuacja, ale wywołuje kontynuację w miejscu został wywołany.
Usłysz, posłuchaj. Zauważ, że jest to również problem z "return", ponieważ pojawia się w większości języków (Java, C, itp.). –
Wierzę, że pod względem technicznym można by utworzyć identyfikator "ja" w odniesieniu do formy lambda. Możesz nawet zrobić to sam, jeśli masz 'case-składni'. Zgadzam się mimo wszystko. Nazwy jawne są na ogół lepsze niż te z nazwami anaforycznymi. –
@ Matthias: Rzeczywiście, "może" i "powinien" są całkowicie różne, szczególnie w tym kontekście. ;-) Zastanawiałem się, dlaczego domyślnie podanie "ja" jest ogólnie rzecz biorąc okropnym pomysłem. –