每个Common Lisp程序员都知道宏是一个强大的工具。除了其他方面,已经使用Common Lisp宏在Lisp 之上添加面向对象而不用更改语言规范; read-macros是另一种具有思维弯曲功能的构造。
另一个允许元编程的程序是Forth。 Forth以略微不同的方式使用“单词”和“生成单词”。
我想知道,从涉及两种语言的人那里,如果普通的lisp宏和前面的结构在广度/功率方面具有可比性:你可以用前者做一些你不能用后者做的事吗?反之亦然?
当然,我不是在谈论两种语言的图灵完整性:我在谈论metaprogramming能力。 C是Turing-complete,但只有傻瓜才会说C宏的功能与Common Lisp相当。
答案 0 :(得分:8)
在我看来,Common Lisp宏类似于Forth 直接词。 (实际上,它们与Lisp读取器宏最相似。)
它们都是程序宏,即可以使用该语言的全部功能。
他们都可以访问源代码输入。
他们都可以输出语言中可以表达的任何内容。 (例如,Lisp中的面向对象扩展,或Forth中的基本控制流构造。)
或许主要区别在于Forth"宏观"输入是字符串,而Lisp宏在解析树上操作。
答案 1 :(得分:6)
我是第四个实施者,在Forth,六个实施,几百个项目问题方面拥有丰富的经验。我还做了一个小的面向对象的扩展(小的,即十几行左右)。 我在LISP方面的经验更多的是在课程层面,但我认为可以公平地说LISP的元编程设施更加系统化,实际上更强大。
在LISP的抽象基础上构建抽象相对容易。在Forth,如果我想在由具有非平凡定义的对象定义的线性空间上定义矩阵。我切换到Python。
原因很明显,至少对我而言。 LISP的创造者,数学家,而查克摩尔是实际程序员的最终范例,从不在理论问题上浪费时间。
这通过以下方式延伸到这个问题。 lisp宏在Lisp的上下文中具有结构,并且至少表明符合一般lisp原则的含义。一个直接的词是另一个程序,可以意味着做任何事情,包括让狗吃晚餐。
答案 2 :(得分:2)
很抱歉,如果下面的讨论看起来有点模糊,但是说的太多了。
我只掌握Lisp的理论知识,而不是亲自动手。
另一方面,Forth可能会(但正常的Forth还没有)在语言中进行完整的元编程。但是元编程是可预期的并且可能但没有连贯的语法。我认为在Lisp中也是如此。
我已经实现了一个非常干净的解决方案,其中包含了一种类似语言的小范式的可能性。为了进行元编程,我们应该能够参考我们所写的内容。因此,当我们编写一个程序立即执行时:
bread eat
我们也应该能够用意图引用相同的短语而不是执行它以保留它以供以后参考。这可以写成例如。
{ bread eat }
上面的短语可能会将创建的对象留在堆栈上。但是,当我们创建一个新单词{
和}
时,我们也有权引用它。
所以,我们想参考:
{ bread
我们怎么能参考呢?暂定语法为:{{ { bread }}
。
如果我们将名称XXX
提供给前一个短语,我们可以将初始短语写为:
XXX eat }
并且上面的短语在离开堆栈时应该正常工作
{ bread eat }
由于我不知道我所说的内容究竟是你在寻找什么,所以只需通过上述推理及其在Forth内部的实现就可以了解每个单词获得执行级别并定义哪个级别这个词的元编程。
显然,我们有第一个无限级别和每个连续级别。因此执行级别基于数学无穷大。
我已经实现了上面的一种Forth和第一级(低于无限)一切顺利。例如,我能够改变语法:
{ bread eat } { tomatos eat } x 3 = if
成:
{ bread eat | tomatos eat } x 3 = if
通过将|
定义为} {
如下:
{{ } { }} "|" define
或者如果你更喜欢它:
2{ } { 2} "|" define
上面的方法在语言中使用了正确的语法语法,并使其成为语言。
所以在我看来,Lisp和Forth都有可能进行元编程,但两者都缺乏作为语言整合部分的可能性。
我在napl.wikispaces.com上有更多详细信息。