匿名的lambdas直接指自己

Har*_*ier 5 scheme racket

Scheme或者方言的任何方言都有一种"自我"操作符,这样匿名的lambdas就可以重复自己,而不需要像Y-combinator那样做或者在letrec等中命名.

就像是:

(lambda (n)
   (cond
     ((= n 0) 1)
     (else (* n (self (- n 1)))))))
Run Code Online (Sandbox Code Playgroud)

Chr*_*ung 9

没有."当前lambda"方法的问题在于Scheme有许多隐藏的lambda.例如:

  • 所有let形式(包括let*,letrec和命名let)
  • do(扩展为命名let)
  • delay,lazy,receive,等.

要求程序员知道最里面的lambda会破坏封装,因为你必须知道所有隐藏的lambda在哪里,而宏编写器不能再使用lambdas作为创建新范围的方法.

如果你问我,全能输.

  • 听,听.请注意,这也是"return"的问题,因为它出现在大多数语言(Java,C等)中. (2认同)

Mat*_*ard 6

编写"照应"宏的传统是在他们身体的词汇范围内定义特殊名称.使用syntax-case,您可以在letrec和之上编写这样的宏lambda.请注意,考虑到规范,下面的定义尽可能卫生(特别是alambda不会影子的隐形使用self).

;; Define a version of lambda that binds the
;; anaphoric variable “self” to the function
;; being defined.
;;
;; Note the use of datum->syntax to specify the
;; scope of the anaphoric identifier. 
(define-syntax alambda
  (lambda (stx)
    (syntax-case stx ()
      [(alambda lambda-list . body)
       (with-syntax ([name (datum->syntax #'alambda 'self)])
         #'(letrec ([name (lambda lambda-list . body)])
             name))])))

;; We can define let in terms of alambda as usual.
(define-syntax let/alambda
  (syntax-rules ()
    [(_ ((var val) ...) . body)
     ((alambda (var ...) . body) val ...)]))

;; The let/alambda macro does not shadow the outer
;; alambda's anaphoric variable, which is lexical
;; with regard to the alambda form.
((alambda (n)
   (if (zero? n)
       1
       (let/alambda ([n-1 (- n 1)])
         (* (self n-1) n))))
 10)
;=> 3628800
Run Code Online (Sandbox Code Playgroud)

大多数人避免使用过敏操作符,因为它们使代码结构不易识别.此外,重构可以很容易地引入问题.(考虑当你let/alambda在另一种alambda形式的上面的阶乘函数中包装表单时会发生什么.很容易忽略它的用法self,特别是如果你不必通过必须明确地输入它来提醒它是相关的.)因此通常优先考虑使用显式名称.一个"标记"版本lambda允许这可以使用一个简单的syntax-rules宏定义:

;; Define a version of lambda that allows the
;; user to specifiy a name for the function
;; being defined.
(define-syntax llambda
  (syntax-rules ()
    [(_ name lambda-list . body)
     (letrec ([name (lambda lambda-list . body)])
       name)]))

;; The factorial function can be expressed
;; using llambda.
((llambda fac (n)
   (if (zero? n)
       1
       (* (fac (- n 1)) n)))
 10)
;=> 3628800
Run Code Online (Sandbox Code Playgroud)

  • 你的`llambda`几乎与[SRFI 31](http://srfi.schemers.org/srfi-31/srfi-31.html)的`rec`相同,后者是该结构的通常名称.:-) (2认同)