让我们对lambda转换感到困惑

时间:2018-03-21 10:38:00

标签: lambda scheme lisp racket let

我目前正在通过great article on Y-combinator完成此Mike Vanier。根据解释,删除了以下行:

  

事实证明,任何let表达式都可以使用以下公式转换为等效的lambda表达式:

     

fragments

本文通过转换说明了这一陈述:

getstring

为:

(let ((x <expr1>)) <expr2>)
    ==> ((lambda (x) <expr2>) <expr1>)

现在,我了解上面的两个代码段是如何以及为何相同,但我无法理解将(define (part-factorial self) (let ((f (self self))) (lambda (n) (if (= n 0) 1 (* n (f (- n 1))))))) 转换为(define (part-factorial self) ((lambda (f) (lambda (n) (if (= n 0) 1 (* n (f (- n 1)))))) (self self))) 的一般方程式:

let

我很欣赏精心解释。

3 个答案:

答案 0 :(得分:4)

我最终弄清楚了自己=)。

我遗漏的一点是:

lambda

(let ((x <expr1>)) <expr2>) ==> ((lambda (x) <expr2>) <expr1>) 位于(let ((x <expr1>)) <expr2>) ==> ((lambda (x) <expr2>) <expr1>) 内的某处,所以它更像是:

x

话虽如此,如果我们将<expr2>替换为(let ((x <expr1>)) <expr-containing-x>) ==> ((lambda (x) <expr-containing-x>) <expr1>)

x

以及:

f

并以不同的颜色突出显示(define (part-factorial self) (let ((f (self self))) (lambda (n) (if (= n 0) 1 (* n (f (- n 1))))))) (define (part-factorial self) ((lambda (f) (lambda (n) (if (= n 0) 1 (* n (f (- n 1)))))) (self self))) x,转换公式应该变得清晰:

x, <expr1> and <expr2> highlighted

答案 1 :(得分:4)

你应该想象一下,有一个非常小的lisp语言有lambda但不是let。你想做的事:

(let ((nsq (square n)))
  (+ nsq nsq))

您知道nsq是一个新变量,let的主体可以成为一个函数:

(lambda (nsq) (+ nsq nsq))

然后你需要使用它来获得相同的值:

((lambda (nsq) (+ nsq nsq)) (square n))

想象一下,您的简单方案有宏,因此,您实现为let

(define-syntax let
  (syntax-rules ()
    [(let ((binding value) ...)
       body ...)
     ((lambda (binding ...)
        body ...)
      value ...)]))

请注意,在许多实现中,这实际上就是这种方式。

答案 2 :(得分:2)

(let ((x 42)) <body>)可让您打开一个可用变量的新环境。在编程语言术语中,我们称它“打开一个新的框架”。

当您撰写x时,您会在<body>内创建42可用的框架,并为其指定值lambda

好吧,还有另一个工具可以让你打开新的框架。实际上,它通常是构建更抽象结构的基本块:它被称为lambda

(lambda (x) <body>)打开一个新的框架,其框架可以使用其参数。 当您撰写x时,您可以<body>使用此功能的lambda

letlet之间的唯一区别是x会立即为lambda分配值,而<body>会等待该值作为参数。< / p>

因此,如果您想使用lambda打包带有直接指定值的((lambda (x) <body>) 42) ,则只需传递该值!

(let ((x 42)) <body>)

这使它完全等同于:

.arrowUp {
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;

  border-bottom: 10px solid black;
  margin-left: -10px;
}