I have read a lot that LISP can redefine syntax on the fly, presumably with macros. I am curious how far does this actually go? Can you redefine the language structure so much that it borderline becomes a compiler for another language? For example, could you change the functional nature of LISP into a more object oriented syntax and semantics, maybe say having syntax closer to something like Ruby?
我已经阅读了很多内容,LISP可以动态地重新定义语法,大概是宏。我好奇这到底有多远?你能重新定义语言结构,以至于它的边界成为另一种语言的编译器吗?例如,您是否可以将LISP的功能性质更改为更面向对象的语法和语义,或许可以说语法更接近像Ruby这样的东西?
Especially, is it possible to get rid of the parenthesis hell using macros? I have learned enough (Emacs-)LISP to customize Emacs with my own micro-features, but I am very curious how far macros can go in customizing the language.
特别是,是否可以使用宏来摆脱括号地狱?我已经学习了足够的(Emacs-)LISP来使用我自己的微功能定制Emacs,但我很好奇宏可以在定制语言方面走多远。
14 个解决方案
#1
33
That's a really good question.
这是一个非常好的问题。
I think it's nuanced but definitely answerable:
我认为这是微妙的,但绝对是负责任的:
Macros are not stuck in s-expressions. See the LOOP macro for a very complex language written using keywords (symbols). So, while you may start and end the loop with parentheses, inside it has its own syntax.
宏不会卡在s表达式中。有关使用关键字(符号)编写的非常复杂的语言,请参阅LOOP宏。因此,虽然您可以用括号开始和结束循环,但它内部有自己的语法。
Example:
(loop for x from 0 below 100
when (even x)
collect x)
That being said, most simple macros just use s-expressions. And you'd be "stuck" using them.
话虽这么说,大多数简单的宏只使用s表达式。而且你会被“卡住”使用它们。
But s-expressions, like Sergio has answered, start to feel right. The syntax gets out of the way and you start coding in the syntax tree.
但像塞尔吉奥所回答的那样,s表达开始感觉正确。语法不受影响,您可以在语法树中开始编码。
As for reader macros, yes, you could conceivably write something like this:
对于读者宏,是的,你可以想象写这样的东西:
#R{
ruby.code.goes.here
}
But you'd need to write your own Ruby syntax parser.
但是你需要编写自己的Ruby语法解析器。
You can also mimic some of the Ruby constructs, like blocks, with macros that compile to the existing Lisp constructs.
您还可以使用编译为现有Lisp构造的宏来模仿某些Ruby构造(如块)。
#B(some lisp (code goes here))
would translate to
会翻译成
(lambda () (some lisp (code goes here)))
See this page for how to do it.
请参阅此页面了解如何操作。
#2
20
Yes, you can redefine the syntax so that Lisp becomes a compiler. You do this using "Reader Macros," which are different from the normal "Compiler Macros" that you're probably thinking of.
是的,您可以重新定义语法,以便Lisp成为编译器。您可以使用“Reader Macros”执行此操作,这与您可能正在考虑的常规“编译器宏”不同。
Common Lisp has the built-in facility to define new syntax for the reader and reader macros to process that syntax. This processing is done at read-time (which comes before compile or eval time). To learn more about defining reader macros in Common Lisp, see the Common Lisp Hyperspec -- you'll want to read Ch. 2, "Syntax" and Ch. 23, "Reader". (I believe Scheme has the same facility, but I'm not as familiar with it -- see the Scheme sources for the Arc programming language).
Common Lisp具有内置功能,可以为读取器和读取器宏定义新语法来处理该语法。此处理在读取时间(在编译或eval时间之前)完成。要了解有关在Common Lisp中定义阅读器宏的更多信息,请参阅Common Lisp Hyperspec - 您将要阅读Ch。 2,“语法”和Ch。 23,“读者”。 (我相信Scheme具有相同的功能,但我对它不熟悉 - 请参阅Arc编程语言的Scheme源代码)。
As a simple example, let's suppose you want Lisp to use curly braces rather than parentheses. This requires something like the following reader definitions:
举个简单的例子,让我们假设您希望Lisp使用花括号而不是括号。这需要类似以下读者定义:
;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
(declare (ignore inchar))
(read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)
(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )
;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )
You're telling Lisp that the { is like a ( and that the } is like a ). Then you create a function (lcurly-brace-reader
) that the reader will call whenever it sees a {, and you use set-macro-character
to assign that function to the {. Then you tell Lisp that ( and ) are like [ and ] (that is, not meaningful syntax).
你告诉Lisp {就像一个(而且}就像一个)。然后你创建一个函数(lcurly-brace-reader),只要它看到{,你就会调用它,并使用set-macro-character将该函数分配给{。然后你告诉Lisp(和)就像[和](也就是说,没有意义的语法)。
Other things you could do include, for example, creating a new string syntax or using [ and ] to enclose in-fix notation and process it into S-expressions.
您可以执行的其他操作包括,例如,创建新的字符串语法或使用[和]括起in-fix表示法并将其处理为S表达式。
You can also go far beyond this, redefining the entire syntax with your own macro characters that will trigger actions in the reader, so the sky really is the limit. This is just one of the reasons why Paul Graham and others keep saying that Lisp is a good language in which to write a compiler.
您还可以远远超出此范围,使用您自己的宏字符重新定义整个语法,这些宏字符将触发阅读器中的操作,因此天空确实是极限。这只是Paul Graham和其他人一直说Lisp是编写编译器的好语言的原因之一。
#3
16
I'm not a Lisp expert, heck I'm not even a Lisp programmer, but after a bit of experimenting with the language I came to the conclusion that after a while the parenthesis start becoming 'invisible' and you start seeing the code as you want it to be. You start paying more attention to the syntactical constructs you create via s-exprs and macros, and less to the lexical form of the text of lists and parenthesis.
我不是Lisp专家,我甚至不是Lisp程序员,但经过一些语言实验后,我得出的结论是,一段时间后,括号开始变为'隐形',你开始看到代码为你想要它。您开始更多地关注通过s-exprs和宏创建的语法结构,而不是注意列表和括号文本的词法形式。
This is specially true if you take advantage of a good editor that helps with the indentation and syntax coloring (try setting the parenthesis to a color very similar to the background).
如果您利用一个有助于缩进和语法着色的好编辑器(尝试将括号设置为与背景非常相似的颜色),则尤其如此。
You might not be able to replace the language completely and get 'Ruby' syntax, but you don't need it. Thanks to the language flexibility you could end having a dialect that feels like you are following the 'Ruby style of programming' if you want, whatever that would mean to you.
您可能无法完全替换语言并获得“Ruby”语法,但您不需要它。由于语言的灵活性,你可以找到一种方言,感觉就像你想要遵循'Ruby风格的编程'一样,无论那对你意味着什么。
I know this is just an empirical observation, but I think I had one of those Lisp enlightenment moments when I realized this.
我知道这只是一个经验观察,但我认为当我意识到这一点时,我有一个Lisp启蒙时刻。
#4
15
Over and over again, newcomers to Lisp want to "get rid of all the parenthesis." It lasts for a few weeks. No project to build a serious general purpose programming syntax on top of the usual S-expression parser ever gets anywhere, because programmers invariably wind up preferring what you currently perceive as "parenthesis hell." It takes a little getting used to, but not much! Once you do get used to it, and you can really appreciate the plasticity of the default syntax, going back to languages where there's only one way to express any particular programming construct is really grating.
一遍又一遍,Lisp的新手想要“摆脱所有的括号”。它会持续几周。没有任何项目可以在通常的S表达式解析器之上构建一个严格的通用编程语法,因为程序员总是喜欢你当前认为是“括号地狱”的东西。它需要一点点习惯,但不是很多!一旦你习惯了它,你就可以真正体会到默认语法的可塑性,回到只有一种方法来表达任何特定编程结构的语言真的很光。
That being said, Lisp is an excellent substrate for building Domain Specific Languages. Just as good as, if not better than, XML.
话虽如此,Lisp是构建领域特定语言的绝佳基础。和XML一样好,如果不是更好的话。
Good luck!
#5
12
The best explanation of Lisp macros I have ever seen is at
我见过的Lisp宏的最佳解释是
https://www.youtube.com/watch?v=4NO83wZVT0A
starting at about 55 minutes in. This is a video of a talk given by Peter Seibel, the author of "Practical Common Lisp", which is the best Lisp textbook there is.
从大约55分钟开始。这是“实用公共Lisp”的作者Peter Seibel给出的一个视频,这是最好的Lisp教科书。
The motivation for Lisp macros is usually hard to explain, because they really come into their own in situations that are too lengthy to present in a simple tutorial. Peter comes up with a great example; you can grasp it completely, and it makes good, proper use of Lisp macros.
Lisp宏的动机通常很难解释,因为它们在一个过于冗长而无法在简单教程中呈现的情况下真正发挥作用。彼得提出了一个很好的榜样;你可以完全掌握它,它可以很好地正确使用Lisp宏。
You asked: "could you change the functional nature of LISP into a more object oriented syntax and semantics". The answer is yes. In fact, Lisp originally didn't have any object-oriented programming at all, not surprising since Lisp has been around since way before object-oriented programming! But when we first learned about OOP in 1978, we were able to add it to Lisp easily, using, among other things, macros. Eventually the Common Lisp Object System (CLOS) was developed, a very powerful object-oriented programming system that fits elegantly into Lisp. The whole thing can be loaded as an extension -- nothing is built-in! It's all done with macros.
你问:“你能否将LISP的功能性改变为更面向对象的语法和语义”。答案是肯定的。事实上,Lisp最初根本没有任何面向对象的编程,因为Lisp在面向对象编程之前就已存在,所以并不奇怪!但是当我们在1978年第一次了解OOP时,我们能够轻松地将它添加到Lisp中,其中包括宏。最终开发了Common Lisp对象系统(CLOS),这是一个非常强大的面向对象编程系统,可以很好地适应Lisp。整个东西可以作为扩展加载 - 没有任何内置!这一切都是用宏完成的。
Lisp has an entirely different feature, called "reader macros", that can be used to extend the surface syntax of the language. Using reader macros, you can make sublanguages that have C-like or Ruby-like syntax. They transform the text into Lisp, internally. These are not used widely by most real Lisp programmers, mainly because it is hard to extend the interactive development environment to understand the new syntax. For example, Emacs indentation commands would be confused by a new syntax. If you're energetic, though, Emacs is extensible too, and you could teach it about your new lexical syntax.
Lisp有一个完全不同的功能,称为“阅读器宏”,可用于扩展语言的表面语法。使用读取器宏,您可以创建具有类似C或类似Ruby的语法的子语言。他们在内部将文本转换为Lisp。大多数真正的Lisp程序员并没有广泛使用它们,主要是因为很难扩展交互式开发环境以理解新语法。例如,Emacs缩进命令会被新语法混淆。但是,如果你精力充沛,Emacs也是可扩展的,你可以教它新的词法语法。
#6
11
Regular macros operate on lists of objects. Most commonly, these objects are other lists (thus forming trees) and symbols, but they can be other objects such as strings, hashtables, user-defined objects, etc. These structures are called s-exps.
常规宏在对象列表上运行。最常见的是,这些对象是其他列表(因此形成树)和符号,但它们可以是其他对象,如字符串,哈希表,用户定义的对象等。这些结构称为s-exps。
So, when you load a source file, your Lisp compiler will parse the text and produce s-exps. Macros operate on these. This works great and it's a marvellous way to extend the language within the spirit of s-exps.
因此,当您加载源文件时,您的Lisp编译器将解析文本并生成s-exps。宏对这些进行操作。这很有效,这是在s-exps精神范围内扩展语言的绝佳方式。
Additionally, the aforementioned parsing process can be extended through "reader macros" that let you customize the way your compiler turns text into s-exps. I suggest, however, that you embrace Lisp's syntax instead of bending it into something else.
此外,上述解析过程可以通过“读取器宏”进行扩展,使您可以自定义编译器将文本转换为s-exps的方式。但是,我建议您接受Lisp的语法,而不是将其弯曲成其他内容。
You sound a bit confused when you mention Lisp's "functional nature" and Ruby's "object-oriented syntax". I'm not sure what "object-oriented syntax" is supposed to be, but Lisp is a multi-paradigm language and it supports object-oriented programming extremelly well.
当你提到Lisp的“功能性”和Ruby的“面向对象语法”时,你听起来有点困惑。我不确定应该是什么“面向对象的语法”,但Lisp是一种多范式语言,它极其支持面向对象的编程。
BTW, when I say Lisp, I mean Common Lisp.
顺便说一下,当我说Lisp时,我指的是Common Lisp。
I suggest you put your prejudices away and give Lisp an honest go.
我建议你放弃偏见,给Lisp一个诚实的去。
#7
9
What you are asking is somewhat like asking how to become an expert chocolatier so that you can remove all that hellish brown stuff from your favourite chocolate cake.
你问的有点像问如何成为一个专家巧克力制作者,以便你可以从你最喜欢的巧克力蛋糕中去除所有那些地狱般的褐色东西。
#8
9
Parenthesis hell? I see no more parenthesis in:
括号地狱?我看到没有更多的括号:
(function toto)
than in:
function(toto);
And in
(if tata (toto)
(titi)
(tutu))
no more than in:
不超过:
if (tata)
toto();
else
{
titi();
tutu();
}
I see less brackets and ';' though.
我看到更少的括号和';'虽然。
#9
6
Yes, you can fundamentally change the syntax, and even escape "the parentheses hell". For that you will need to define a new reader syntax. Look into reader macros.
是的,你可以从根本上改变语法,甚至逃避“括号地狱”。为此,您需要定义新的阅读器语法。查看读者宏。
I do suspect however that to reach the level of Lisp expertise to program such macros you will need to immerse yourself in the language to such an extent that you will no longer consider parenthese "hell". I.e. by the time you know how to avoid them, you will have come to accept them as a good thing.
但我确实怀疑要达到Lisp专业知识的水平来编程这样的宏,你需要让自己沉浸在语言中,以至于你将不再考虑括号“地狱”。即当你知道如何避免它们时,你会接受它们作为一件好事。
#10
2
If you want lisp to look like Ruby use Ruby.
如果你希望lisp看起来像Ruby使用Ruby。
It's possible to use Ruby (and Python) in a very lisp like way which is one of the main reasons they have gained acceptance so quickly.
可以以非常类似的方式使用Ruby(和Python),这是他们如此迅速地获得认可的主要原因之一。
#11
2
see this example of how reader macros can extend the lisp reader with complex tasks like XML templating:
请参阅此示例,了解读者宏如何使用XML模板等复杂任务扩展lisp阅读器:
http://common-lisp.net/project/cl-quasi-quote/present-class.html
this user library compiles the static parts of the XML into UTF-8 encoded literal byte arrays at compile time that are ready to be write-sequence'd into the network stream. and they are usable in normal lisp macros, they are orthogonal... the placement of the comma character influences which parts are constant and which should be evaluated at runtime.
此用户库在编译时将XML的静态部分编译为UTF-8编码的文字字节数组,这些数组已准备好写入网络流中。它们可以在普通的lisp宏中使用,它们是正交的...逗号字符的位置会影响哪些部分是常量的,哪些部分应该在运行时进行评估。
more details available at: http://common-lisp.net/project/cl-quasi-quote/
更多详情请访问:http://common-lisp.net/project/cl-quasi-quote/
another project that for Common Lisp syntax extensions: http://common-lisp.net/project/cl-syntax-sugar/
Common Lisp语法扩展的另一个项目:http://common-lisp.net/project/cl-syntax-sugar/
#12
1
@sparkes
Sometimes LISP is the clear language choice, namely Emacs extensions. I'm sure I could use Ruby to extend Emacs if I wanted to, but Emacs was designed to be extended with LISP, so it seems to make sense to use it in that situation.
有时LISP是明确的语言选择,即Emacs扩展。我确信如果我愿意,我可以使用Ruby来扩展Emacs,但是Emacs的设计是为了扩展LISP,所以在这种情况下使用它似乎是有意义的。
#13
1
It's a tricky question. Since lisp is already structurally so close to a parse tree the difference between a large number of macros and implementing your own mini-language in a parser generator isn't very clear. But, except for the opening and closing paren, you could very easily end up with something that looks nothing like lisp.
这是一个棘手的问题。由于lisp已经在结构上非常接近解析树,因此大量宏与在解析器生成器中实现自己的迷你语言之间的区别并不十分清楚。但是,除了开幕式和闭幕式之外,你可以很容易地得到一些看起来不像lisp的东西。
#14
1
One of the uses of macros that blew my mind was the compile-time verification of SQL requests against DB.
我想到的宏的一个用途是针对DB的SQL请求的编译时验证。
Once you realize you have the full language at hand at compile-time, it opens up interesting new perspectives. Which also means you can shoot yourself in the foot in interesting new ways (like rendering compilation not reproducible, which can very easily turn into a debugging nightmare).
一旦你意识到你在编译时就掌握了完整的语言,它就会打开有趣的新视角。这也意味着你可以用有趣的新方式射击自己(比如渲染编译不可重复,这很容易变成调试噩梦)。
#1
33
That's a really good question.
这是一个非常好的问题。
I think it's nuanced but definitely answerable:
我认为这是微妙的,但绝对是负责任的:
Macros are not stuck in s-expressions. See the LOOP macro for a very complex language written using keywords (symbols). So, while you may start and end the loop with parentheses, inside it has its own syntax.
宏不会卡在s表达式中。有关使用关键字(符号)编写的非常复杂的语言,请参阅LOOP宏。因此,虽然您可以用括号开始和结束循环,但它内部有自己的语法。
Example:
(loop for x from 0 below 100
when (even x)
collect x)
That being said, most simple macros just use s-expressions. And you'd be "stuck" using them.
话虽这么说,大多数简单的宏只使用s表达式。而且你会被“卡住”使用它们。
But s-expressions, like Sergio has answered, start to feel right. The syntax gets out of the way and you start coding in the syntax tree.
但像塞尔吉奥所回答的那样,s表达开始感觉正确。语法不受影响,您可以在语法树中开始编码。
As for reader macros, yes, you could conceivably write something like this:
对于读者宏,是的,你可以想象写这样的东西:
#R{
ruby.code.goes.here
}
But you'd need to write your own Ruby syntax parser.
但是你需要编写自己的Ruby语法解析器。
You can also mimic some of the Ruby constructs, like blocks, with macros that compile to the existing Lisp constructs.
您还可以使用编译为现有Lisp构造的宏来模仿某些Ruby构造(如块)。
#B(some lisp (code goes here))
would translate to
会翻译成
(lambda () (some lisp (code goes here)))
See this page for how to do it.
请参阅此页面了解如何操作。
#2
20
Yes, you can redefine the syntax so that Lisp becomes a compiler. You do this using "Reader Macros," which are different from the normal "Compiler Macros" that you're probably thinking of.
是的,您可以重新定义语法,以便Lisp成为编译器。您可以使用“Reader Macros”执行此操作,这与您可能正在考虑的常规“编译器宏”不同。
Common Lisp has the built-in facility to define new syntax for the reader and reader macros to process that syntax. This processing is done at read-time (which comes before compile or eval time). To learn more about defining reader macros in Common Lisp, see the Common Lisp Hyperspec -- you'll want to read Ch. 2, "Syntax" and Ch. 23, "Reader". (I believe Scheme has the same facility, but I'm not as familiar with it -- see the Scheme sources for the Arc programming language).
Common Lisp具有内置功能,可以为读取器和读取器宏定义新语法来处理该语法。此处理在读取时间(在编译或eval时间之前)完成。要了解有关在Common Lisp中定义阅读器宏的更多信息,请参阅Common Lisp Hyperspec - 您将要阅读Ch。 2,“语法”和Ch。 23,“读者”。 (我相信Scheme具有相同的功能,但我对它不熟悉 - 请参阅Arc编程语言的Scheme源代码)。
As a simple example, let's suppose you want Lisp to use curly braces rather than parentheses. This requires something like the following reader definitions:
举个简单的例子,让我们假设您希望Lisp使用花括号而不是括号。这需要类似以下读者定义:
;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
(declare (ignore inchar))
(read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)
(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )
;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )
You're telling Lisp that the { is like a ( and that the } is like a ). Then you create a function (lcurly-brace-reader
) that the reader will call whenever it sees a {, and you use set-macro-character
to assign that function to the {. Then you tell Lisp that ( and ) are like [ and ] (that is, not meaningful syntax).
你告诉Lisp {就像一个(而且}就像一个)。然后你创建一个函数(lcurly-brace-reader),只要它看到{,你就会调用它,并使用set-macro-character将该函数分配给{。然后你告诉Lisp(和)就像[和](也就是说,没有意义的语法)。
Other things you could do include, for example, creating a new string syntax or using [ and ] to enclose in-fix notation and process it into S-expressions.
您可以执行的其他操作包括,例如,创建新的字符串语法或使用[和]括起in-fix表示法并将其处理为S表达式。
You can also go far beyond this, redefining the entire syntax with your own macro characters that will trigger actions in the reader, so the sky really is the limit. This is just one of the reasons why Paul Graham and others keep saying that Lisp is a good language in which to write a compiler.
您还可以远远超出此范围,使用您自己的宏字符重新定义整个语法,这些宏字符将触发阅读器中的操作,因此天空确实是极限。这只是Paul Graham和其他人一直说Lisp是编写编译器的好语言的原因之一。
#3
16
I'm not a Lisp expert, heck I'm not even a Lisp programmer, but after a bit of experimenting with the language I came to the conclusion that after a while the parenthesis start becoming 'invisible' and you start seeing the code as you want it to be. You start paying more attention to the syntactical constructs you create via s-exprs and macros, and less to the lexical form of the text of lists and parenthesis.
我不是Lisp专家,我甚至不是Lisp程序员,但经过一些语言实验后,我得出的结论是,一段时间后,括号开始变为'隐形',你开始看到代码为你想要它。您开始更多地关注通过s-exprs和宏创建的语法结构,而不是注意列表和括号文本的词法形式。
This is specially true if you take advantage of a good editor that helps with the indentation and syntax coloring (try setting the parenthesis to a color very similar to the background).
如果您利用一个有助于缩进和语法着色的好编辑器(尝试将括号设置为与背景非常相似的颜色),则尤其如此。
You might not be able to replace the language completely and get 'Ruby' syntax, but you don't need it. Thanks to the language flexibility you could end having a dialect that feels like you are following the 'Ruby style of programming' if you want, whatever that would mean to you.
您可能无法完全替换语言并获得“Ruby”语法,但您不需要它。由于语言的灵活性,你可以找到一种方言,感觉就像你想要遵循'Ruby风格的编程'一样,无论那对你意味着什么。
I know this is just an empirical observation, but I think I had one of those Lisp enlightenment moments when I realized this.
我知道这只是一个经验观察,但我认为当我意识到这一点时,我有一个Lisp启蒙时刻。
#4
15
Over and over again, newcomers to Lisp want to "get rid of all the parenthesis." It lasts for a few weeks. No project to build a serious general purpose programming syntax on top of the usual S-expression parser ever gets anywhere, because programmers invariably wind up preferring what you currently perceive as "parenthesis hell." It takes a little getting used to, but not much! Once you do get used to it, and you can really appreciate the plasticity of the default syntax, going back to languages where there's only one way to express any particular programming construct is really grating.
一遍又一遍,Lisp的新手想要“摆脱所有的括号”。它会持续几周。没有任何项目可以在通常的S表达式解析器之上构建一个严格的通用编程语法,因为程序员总是喜欢你当前认为是“括号地狱”的东西。它需要一点点习惯,但不是很多!一旦你习惯了它,你就可以真正体会到默认语法的可塑性,回到只有一种方法来表达任何特定编程结构的语言真的很光。
That being said, Lisp is an excellent substrate for building Domain Specific Languages. Just as good as, if not better than, XML.
话虽如此,Lisp是构建领域特定语言的绝佳基础。和XML一样好,如果不是更好的话。
Good luck!
#5
12
The best explanation of Lisp macros I have ever seen is at
我见过的Lisp宏的最佳解释是
https://www.youtube.com/watch?v=4NO83wZVT0A
starting at about 55 minutes in. This is a video of a talk given by Peter Seibel, the author of "Practical Common Lisp", which is the best Lisp textbook there is.
从大约55分钟开始。这是“实用公共Lisp”的作者Peter Seibel给出的一个视频,这是最好的Lisp教科书。
The motivation for Lisp macros is usually hard to explain, because they really come into their own in situations that are too lengthy to present in a simple tutorial. Peter comes up with a great example; you can grasp it completely, and it makes good, proper use of Lisp macros.
Lisp宏的动机通常很难解释,因为它们在一个过于冗长而无法在简单教程中呈现的情况下真正发挥作用。彼得提出了一个很好的榜样;你可以完全掌握它,它可以很好地正确使用Lisp宏。
You asked: "could you change the functional nature of LISP into a more object oriented syntax and semantics". The answer is yes. In fact, Lisp originally didn't have any object-oriented programming at all, not surprising since Lisp has been around since way before object-oriented programming! But when we first learned about OOP in 1978, we were able to add it to Lisp easily, using, among other things, macros. Eventually the Common Lisp Object System (CLOS) was developed, a very powerful object-oriented programming system that fits elegantly into Lisp. The whole thing can be loaded as an extension -- nothing is built-in! It's all done with macros.
你问:“你能否将LISP的功能性改变为更面向对象的语法和语义”。答案是肯定的。事实上,Lisp最初根本没有任何面向对象的编程,因为Lisp在面向对象编程之前就已存在,所以并不奇怪!但是当我们在1978年第一次了解OOP时,我们能够轻松地将它添加到Lisp中,其中包括宏。最终开发了Common Lisp对象系统(CLOS),这是一个非常强大的面向对象编程系统,可以很好地适应Lisp。整个东西可以作为扩展加载 - 没有任何内置!这一切都是用宏完成的。
Lisp has an entirely different feature, called "reader macros", that can be used to extend the surface syntax of the language. Using reader macros, you can make sublanguages that have C-like or Ruby-like syntax. They transform the text into Lisp, internally. These are not used widely by most real Lisp programmers, mainly because it is hard to extend the interactive development environment to understand the new syntax. For example, Emacs indentation commands would be confused by a new syntax. If you're energetic, though, Emacs is extensible too, and you could teach it about your new lexical syntax.
Lisp有一个完全不同的功能,称为“阅读器宏”,可用于扩展语言的表面语法。使用读取器宏,您可以创建具有类似C或类似Ruby的语法的子语言。他们在内部将文本转换为Lisp。大多数真正的Lisp程序员并没有广泛使用它们,主要是因为很难扩展交互式开发环境以理解新语法。例如,Emacs缩进命令会被新语法混淆。但是,如果你精力充沛,Emacs也是可扩展的,你可以教它新的词法语法。
#6
11
Regular macros operate on lists of objects. Most commonly, these objects are other lists (thus forming trees) and symbols, but they can be other objects such as strings, hashtables, user-defined objects, etc. These structures are called s-exps.
常规宏在对象列表上运行。最常见的是,这些对象是其他列表(因此形成树)和符号,但它们可以是其他对象,如字符串,哈希表,用户定义的对象等。这些结构称为s-exps。
So, when you load a source file, your Lisp compiler will parse the text and produce s-exps. Macros operate on these. This works great and it's a marvellous way to extend the language within the spirit of s-exps.
因此,当您加载源文件时,您的Lisp编译器将解析文本并生成s-exps。宏对这些进行操作。这很有效,这是在s-exps精神范围内扩展语言的绝佳方式。
Additionally, the aforementioned parsing process can be extended through "reader macros" that let you customize the way your compiler turns text into s-exps. I suggest, however, that you embrace Lisp's syntax instead of bending it into something else.
此外,上述解析过程可以通过“读取器宏”进行扩展,使您可以自定义编译器将文本转换为s-exps的方式。但是,我建议您接受Lisp的语法,而不是将其弯曲成其他内容。
You sound a bit confused when you mention Lisp's "functional nature" and Ruby's "object-oriented syntax". I'm not sure what "object-oriented syntax" is supposed to be, but Lisp is a multi-paradigm language and it supports object-oriented programming extremelly well.
当你提到Lisp的“功能性”和Ruby的“面向对象语法”时,你听起来有点困惑。我不确定应该是什么“面向对象的语法”,但Lisp是一种多范式语言,它极其支持面向对象的编程。
BTW, when I say Lisp, I mean Common Lisp.
顺便说一下,当我说Lisp时,我指的是Common Lisp。
I suggest you put your prejudices away and give Lisp an honest go.
我建议你放弃偏见,给Lisp一个诚实的去。
#7
9
What you are asking is somewhat like asking how to become an expert chocolatier so that you can remove all that hellish brown stuff from your favourite chocolate cake.
你问的有点像问如何成为一个专家巧克力制作者,以便你可以从你最喜欢的巧克力蛋糕中去除所有那些地狱般的褐色东西。
#8
9
Parenthesis hell? I see no more parenthesis in:
括号地狱?我看到没有更多的括号:
(function toto)
than in:
function(toto);
And in
(if tata (toto)
(titi)
(tutu))
no more than in:
不超过:
if (tata)
toto();
else
{
titi();
tutu();
}
I see less brackets and ';' though.
我看到更少的括号和';'虽然。
#9
6
Yes, you can fundamentally change the syntax, and even escape "the parentheses hell". For that you will need to define a new reader syntax. Look into reader macros.
是的,你可以从根本上改变语法,甚至逃避“括号地狱”。为此,您需要定义新的阅读器语法。查看读者宏。
I do suspect however that to reach the level of Lisp expertise to program such macros you will need to immerse yourself in the language to such an extent that you will no longer consider parenthese "hell". I.e. by the time you know how to avoid them, you will have come to accept them as a good thing.
但我确实怀疑要达到Lisp专业知识的水平来编程这样的宏,你需要让自己沉浸在语言中,以至于你将不再考虑括号“地狱”。即当你知道如何避免它们时,你会接受它们作为一件好事。
#10
2
If you want lisp to look like Ruby use Ruby.
如果你希望lisp看起来像Ruby使用Ruby。
It's possible to use Ruby (and Python) in a very lisp like way which is one of the main reasons they have gained acceptance so quickly.
可以以非常类似的方式使用Ruby(和Python),这是他们如此迅速地获得认可的主要原因之一。
#11
2
see this example of how reader macros can extend the lisp reader with complex tasks like XML templating:
请参阅此示例,了解读者宏如何使用XML模板等复杂任务扩展lisp阅读器:
http://common-lisp.net/project/cl-quasi-quote/present-class.html
this user library compiles the static parts of the XML into UTF-8 encoded literal byte arrays at compile time that are ready to be write-sequence'd into the network stream. and they are usable in normal lisp macros, they are orthogonal... the placement of the comma character influences which parts are constant and which should be evaluated at runtime.
此用户库在编译时将XML的静态部分编译为UTF-8编码的文字字节数组,这些数组已准备好写入网络流中。它们可以在普通的lisp宏中使用,它们是正交的...逗号字符的位置会影响哪些部分是常量的,哪些部分应该在运行时进行评估。
more details available at: http://common-lisp.net/project/cl-quasi-quote/
更多详情请访问:http://common-lisp.net/project/cl-quasi-quote/
another project that for Common Lisp syntax extensions: http://common-lisp.net/project/cl-syntax-sugar/
Common Lisp语法扩展的另一个项目:http://common-lisp.net/project/cl-syntax-sugar/
#12
1
@sparkes
Sometimes LISP is the clear language choice, namely Emacs extensions. I'm sure I could use Ruby to extend Emacs if I wanted to, but Emacs was designed to be extended with LISP, so it seems to make sense to use it in that situation.
有时LISP是明确的语言选择,即Emacs扩展。我确信如果我愿意,我可以使用Ruby来扩展Emacs,但是Emacs的设计是为了扩展LISP,所以在这种情况下使用它似乎是有意义的。
#13
1
It's a tricky question. Since lisp is already structurally so close to a parse tree the difference between a large number of macros and implementing your own mini-language in a parser generator isn't very clear. But, except for the opening and closing paren, you could very easily end up with something that looks nothing like lisp.
这是一个棘手的问题。由于lisp已经在结构上非常接近解析树,因此大量宏与在解析器生成器中实现自己的迷你语言之间的区别并不十分清楚。但是,除了开幕式和闭幕式之外,你可以很容易地得到一些看起来不像lisp的东西。
#14
1
One of the uses of macros that blew my mind was the compile-time verification of SQL requests against DB.
我想到的宏的一个用途是针对DB的SQL请求的编译时验证。
Once you realize you have the full language at hand at compile-time, it opens up interesting new perspectives. Which also means you can shoot yourself in the foot in interesting new ways (like rendering compilation not reproducible, which can very easily turn into a debugging nightmare).
一旦你意识到你在编译时就掌握了完整的语言,它就会打开有趣的新视角。这也意味着你可以用有趣的新方式射击自己(比如渲染编译不可重复,这很容易变成调试噩梦)。