对于Racket编程语言,为什么不将lambda视为函数?例如,不能将其定义为像这样的高阶函数。(define (my-lambda args body) (lambda args body))
有一个关键的区别是您的问题丢失了:
lambda
是语法。甲lambda
形式是表达的形式,其值是一个过程。可以说,“ lambda是一个函数”的问题始于类型错误,因为lambda和过程不在同一个世界中。
但是让我们搁置一旁。另一种看待此问题的方法是根据评估规则进行思考。对于将过程应用到参数的默认Scheme评估规则可以用伪代码表示,如下所示:
(define (eval-application expr env)
(let ((values
;; Evaluate each subexpression in the same environment as the
;; enclosing expression, and collect the result values.
(map (lambda (subexpr) (eval subexpr env))
expr)))
;; Apply the first value (which must be a procedure) to the
;; other ones in the results.
(apply (car values) (cdr values))))
用英语讲:
apply
其余列表的第一个结果(必须对过程求值)。现在,另一个lambda
不能成为过程的原因是该求值规则不适用于lambda
表达式。尤其要注意的lambda
是不要立即评估其身体!my-lambda
如果您尝试以这种方式使用它,尤其是这会困扰您:
(my-lambda (x) (+ x x))
...(x)
中间部分必须立即作为x
在整个表达式出现的环境中命名的过程的调用进行评估。该(+ x x)
也必须立即进行评估。
因此lambda
需要自己的评估规则。正如Basile的答案所指出的那样,通常在Scheme系统实现中将其实现为原语,但是我们可以使用如下伪代码来绘制它:
;;;
;;; Evaluate an expression of this form, returning a procedure:
;;;
;;; (lambda <formals> <body> ...)
;;;
(define (eval-lambda expr env)
(let ((formals (second expr))
(body (cddr expr)))
;; We don't evaluate `body` right away, we return a procedure.
(lambda args
;; `formals` is never evaluated, since it's not really an
;; expression on its own, but rather a subpart that cannot
;; be severed from its enclosing `lambda`. Or if we want to
;; say it all fancy, the `formals` is *syncategorematic*...
(let ((bindings (make-bindings formals args)))
;; When the procedure we return is called, *then* we evaluate
;; the `body`--but in an extended environment that binds its
;; formal parameters to the arguments supplied in that call.
(eval `(begin ,@body) (extend-environment env bindings))))))
;;;
;;; "Tie" each formal parameter of the procedure to the corresponding
;;; argument values supplied in a given call. Returns the bindings
;;; as an association list.
;;;
(define (make-bindings formals args)
(cond ((symbol? formals)
`((,formals . args)))
((pair? formals)
`((,(car formals) . ,(car args))
,@(make-bindings (cdr formals) (cdr args))))))
为了理解此伪代码,经过时间考验的是研究许多Scheme书籍之一,这些书籍展示了如何构建元循环解释器(用Scheme编写的Scheme解释器)。例如,请参阅“计算机程序的结构和解释”这一节。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句