【问题标题】:Scheme/Drracket, avoid using let, still not evaluating same function twiceScheme/Drracket,避免使用 let,仍然没有两次评估相同的函数
【发布时间】:2017-04-16 13:17:51
【问题描述】:
我有一个无法解决的编码类作业:(
(define f
(lambda (x)
(i (g x) (h (g x)))))
i、g 和 h 只是任意函数名称。
这是代码,我需要重写它,以便仅对 (g x) 进行一次评估,但不使用 let (或它的任何变体),仅使用 define 和 lambda 作为预定义函数。我也不允许从f 中进行计算,也就是说,所有计算都必须在该函数内部进行。
【问题讨论】:
标签:
lambda
scheme
racket
let
【解决方案1】:
简单的方法是
(define f
(lambda (x)
(define intermediary (g x))
(i intermediary (h intermediary))))
更复杂的是
(define f
(lambda (x)
((lambda (intermediary) ; anonymous procedure
(i intermediary (h intermediary)))
(g x))))
或者,避免匿名过程并将其命名为sub:
(define f
(lambda (x)
(define sub
(lambda (intermediary)
(i intermediary (h intermediary))))
(sub (g x))))
【解决方案2】:
有趣的是,您不允许使用 let 的任何变体,而允许使用 define 和 lambda,我肯定会说这是 let 的真正变体(反之亦然)。
(let ((v1 expr1) ...)
body ...)
和
一样
((lambda (v1 ...)
body ...) expr1 ...)
所以let 是lambda 的变体。因此:
(define f
(lambda (x)
(let ((gx (g x)))
(i gx (h gx)))))
当然可以改写为:
(define f
(lambda (x)
((lambda (gx)
(i gx (h gx)))
(g x))))
现在想象一下,在(define f ..) 之前我们定义了其他freee 变量。可以重写为:
((lambda (i)
((lambda (h)
((lambda (g)
((lambda (f)
rest-of-program ...)
(lambda (x)
((lambda (gx)
(i gx (h gx)))
(g x)))))
(lambda (v) g-expression)))
(lambda (v) h-expression)))
(lambda (v1 v2) i-expression))
如果绑定变量之一实际上需要在其闭包中进一步绑定,则真正的扩展可能会稍微复杂一些,但对于原语来说这是可行的。