Lisp报价混淆 [英] Confused by Lisp Quoting

查看:120
本文介绍了Lisp报价混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于对Lisp中的列表进行评估的问题.

I have a question concerning evaluation of lists in lisp.

为什么未评估(a)(+ a 1)

(defun test (a) (+ a 1))

就像(print 4)不在此处评估

(if (< 1 2) (print 3) (print 4))

但是在这里评估(print (+ 2 3))

(test (print (+ 2 3)))

它们是否与标准库函数有关?我可以在lisp程序中定义类似的功能吗?

Does it have something to do with them being standard library functions? Is it possible for me to define functions like that in my lisp program?

推荐答案

您可能已经知道,Lisp复合形式通常是从外部进行处理的.您必须查看最外层嵌套的第一个位置的符号才能理解形式.该符号完全确定表格的含义.

As you probably know, Lisp compound forms are generally processed from the outside in. You must look at the symbol in the first position of the outermost nesting to understand a form. That symbol completely determines the meaning of the form.

;; Common Lisp: define a class A derived from B and C
(defclass a (b c) ())

;; Common Lisp: define a function of two arguments
(defun a (b c) ())

;; add A to the result of calling function B on variable C:
(+ a (b c))

传统上,Lisp方言将形式分为运算符形式和函数调用形式.运算符形式具有完全任意的含义,由编译或解释该函数的代码段确定(例如,求值仅遍历所有函数调用的参数形式,然后将结果值传递给该函数).

Traditionally, Lisp dialects have divided forms into operator forms and function call forms. An operator form has a completely arbitrary meaning, determined by the piece of code which compiles or interprets that functions (e.g. the evaluation simply recurses over all of the function call's argument forms, and the resulting values are passed to the function).

从早期的历史来看,Lisp允许用户编写自己的运算符.有两种解决方法:解释运算符(历史上称为fexprs)和编译运算符(称为宏).两者都围绕一个以未评估形式作为参数的函数的概念,以便它可以实现自定义策略,从而以新的行为扩展评估模型.

From the early history, Lisp has allowed users to write their own operators. There existed two approaches to this: interpretive operators (historically known as fexprs) and compiling operators known as macros. Both hinge around the idea of a function which receives the unevaluated form as an argument, so that it can implement a custom strategy, thereby extending the evaluation model with new behaviors.

fexpr类型运算符只是在运行时交给表单,还有一个环境对象,它可以通过它查找变量等的值.然后,该操作员浏览表单并实现行为.

A fexpr type operator is simply handed the form at run-time, along with an environment object with which it can look up the values of variables and such. That operator then walks the form and implements the behavior.

宏运算符在宏扩展时(通常在读取或评估或编译顶级表单时发生)进行处理.它的工作不是解释表单的行为,而是通过生成代码来翻译它. IE.宏是微型编译器. (生成的代码可以包含更多的宏调用;宏扩展器会处理这一问题,确保所有宏调用都被抽取.)

A macro operator is handed the form at macro-expansion time (which usually happens when top-level forms are read, just before they are evaluated or compiled). Its job is not to interpret the form's behavior, but instead to translate it by generating code. I.e. a macro is a mini compiler. (Generated code can contain more macro calls; the macro expander will take care of that, ensuring that all macro calls are decimated.)

fexpr方法失宠,很可能是因为它效率低下.基本上,它使编译变得不可能,而Lisp黑客则重视编译. (Lisp早在1960年就已经是一种编译语言.)fexpr方法也对词汇环境怀有敌意.它要求fexpr(它是一个函数)能够对调用它的形式的变量绑定环境进行对等,这是一种词法作用域所不允许的封装违规.

The fexpr approach fell out of favor, most likely because it is inefficient. It basically makes compilation impossible, whereas Lisp hackers valued compilation. (Lisp was already a compiled language from as early as circa 1960.) The fexpr approach is also hostile toward lexical environments; it requires the fexpr, which is a function, to be able to peer into the variable binding environment of the form in which its invoked, which is a kind of encapsulation violation that is not allowed by lexical scopes.

宏写入稍微有点困难,并且在某些方面不如fexprs灵活,但是从1960年代到70年代,Lisp改进了对宏写入的支持,从而使其尽可能地容易. Macro最初接收了整个表格,然后不得不自己解析.宏定义系统发展成为一种为宏函数提供参数的参数,这些参数以易于消化的方式接收分解后的语法,包括语法的某些嵌套方面.还开发了用于编写代码模板的反引号语法,使表达代码生成更加容易.

Macro writing is slightly more difficult, and in some ways less flexible than fexprs, but support for macro writing improved in Lisp through the 1960's into the 70's to make it close to as easy as possible. Macro originally had receive the whole form and then have to parse it themselves. The macro-defining system developed into something that provides macro functions with arguments that receive the broken-down syntax in easily digestible pieces, including some nested aspects of the syntax. The backquote syntax for writing code templates was also developed, making it much easier to express code generation.

因此,为了回答您的问题,我该如何自己编写类似的表格?例如,如果:

So to answer your question, how can I write forms like that myself? For instance if:

;; Imitation of old-fashioned technique: receive the whole form,
;; extract parts from it and return the translation.
;; Common Lisp defmacro supports this via the &whole keyword
;; in macro lambda lists which lets us have access to the whole form.
;;
;; (Because we are using defmacro, we need to declare arguments "an co &optional al",
;; to make this a three argument macro with an optional third argument, but
;; we don't use those arguments. In ancient lisps, they would not appear:
;; a macro would be a one-argument function, and would have to check the number
;; of arguments itself, to flag bad syntax like (my-if 42) or (my-if).)
;;
(defmacro my-if (&whole if-form an co &optional al)
  (let ((antecedent (second if-form))   ;; extract pieces ourselves
        (consequent (third if-form))    ;; from whole (my-if ...) form
        (alternative (fourth if-form)))
    (list 'cond (list antecedent consequent) (list t alternative))))

;; "Modern" version. Use the parsed arguments, and also take advantage of
;; backquote syntax to write the COND with a syntax that looks like the code.
(defmacro my-if (antecedent consequent &optional alternative)
   `(cond (,antecedent ,consequent) (t ,alternative))))

这是一个合适的示例,因为最初Lisp仅具有cond.麦卡锡的《 Lisp》中没有if.后来,人们发明了语法糖",就像作为宏扩展到cond一样,就像上面的my-if一样.

This is a fitting example because originally Lisp only had cond. There was no if in McCarthy's Lisp. That "syntactic sugar" was invented later, probably as a macro expanding to cond, just like my-if above.

这篇关于Lisp报价混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆