Functional programming 为什么lambda不是一个函数
对于Racket编程语言,为什么lambda不被视为一个函数? 例如,它不能定义为这样的高阶函数。Functional programming 为什么lambda不是一个函数,functional-programming,racket,Functional Programming,Racket,对于Racket编程语言,为什么lambda不被视为一个函数? 例如,它不能定义为这样的高阶函数。 (定义(我的lambda参数体) (lambda args body))lambda需要成为Scheme中的核心语言功能(如if,let,defineare),因为它正在构建一个so,因此需要管理一组已关闭的or(并以某种方式将它们的绑定放在闭包中) 例如: (define (translate d) (lambda (x) (+ d x))) 当您调用或计算(translate 3)时,d是3
(定义(我的lambda参数体)
(lambda args body))
lambda
需要成为Scheme中的核心语言功能(如if
,let
,define
are),因为它正在构建一个so,因此需要管理一组已关闭的or(并以某种方式将它们的绑定放在闭包中)
例如:
(define (translate d) (lambda (x) (+ d x)))
当您调用或计算(translate 3)
时,d
是3,因此动态构造的闭包应该记住d
绑定到3。顺便说一句,您通常希望(translate 3)
和(translate 7)
的结果是两个不同的闭包,它们共享一些公共代码(但对d
具有不同的绑定)
还可以阅读关于
解释所有细节需要一整本书。幸运的是,C.Queinnec写了这本书,所以请阅读他的书
(如果你读法语,你可以读那本书的最新法语)
另见
另请阅读wikipage关于
注:您可以,以及一些Lisp实现(特别是,可能)这样做,将
lambda
定义为一些-例如,它将扩展为以特定于实现的方式构建一些闭包(但lambda
不能定义为函数)。您的问题缺少一个关键区别:
lambda
是语法(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))))
;;;
;;; 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))))))
英文:
将第一个结果(必须已对某个过程进行评估)应用于其余结果的列表
lambda
不能成为过程的另一个原因是该求值规则不适用于lambda
表达式。特别是,lambda
的要点是不要立即评估它的身体!特别是,这正是困扰您的my lambda
-如果您尝试以这种方式使用它:
(my-lambda (x) (+ x x))
在整个表达式出现的环境中,必须立即将中间的<代码>(x)< /> >作为调用一个名为“代码> x/CODE”的过程的调用。还必须立即评估(+x x)
因此,lambda
需要自己的评估规则。正如Basile的回答所指出的,这通常是作为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))))
;;;
;;; 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))))))
;;;
;;; 计算此表单的表达式,返回一个过程:
;;;
;;; (拉姆达…)
;;;
(定义(评估lambda expr env)
(格式(第二次扩展))
(正文(cddr expr)))
我们不立即评估“body”,而是返回一个过程。
(λargs)
“formals”从未被评估过,因为它不是真正的
表达本身,而是一个不能表达的子部分
;从它的封闭的“lambda”中分离出来。或者如果我们愿意的话
;说得天花乱坠,'formals'是“同步分类的”*。。。
(let((绑定(使绑定形式为args)))
;当我们返回的过程被调用时,*然后*我们计算
;`body`--但是在一个扩展的环境中,绑定了它的
;调用中提供的参数的形式参数。
(eval`(begin,@body)(扩展环境环境环境绑定‘‘‘‘‘‘‘)’)
;;;
;;; 将程序的每个形式参数与相应的
;;; 给定调用中提供的参数值。返回绑定
;;; 作为关联列表。
;;;
(定义(使绑定形式为args)
(条件((符号?形式)
`(,formals.args)))
((成对形式)
`(,(汽车形式),(汽车参数))
,@(制作绑定(cdr格式)(cdr参数()()())))
为了理解这个伪代码,经过时间考验的事情是学习许多Scheme书籍中的一本,这些书籍演示了如何构建元循环解释器(用Scheme编写的Scheme解释器)。参见示例。在Scheme行话中,我们在整个标准报告中使用术语过程而不是函数。因此,由于这是关于scheme方言的,我将使用术语“过程”
用标准的#之类的语言!球拍
和#!r6rs
在使用新的词汇环境对主体进行求值之前,过程会先求值它们的参数。因此,由于if
和lambda
比过程有特殊的求值规则,因此特殊形式和宏是引入新语法的方式
用像#这样的惰性语言!lazy
racket求值是根据需要进行的,因此许多在渴望语言中实现为宏/特殊形式的表单可以实现为过程。例如,您可以使用cond
将if
作为一个过程,但不能使用if
将cond
作为一个过程,因为这些术语本身将在访问时作为表单进行评估,而例如(cond(#t'真值))
将失败,因为\t
不是一个过程lambda
与参数列表有类似的问题。函数调用(e0 e1 e2)的计算如下
f
的函数体在