我已经阅读了很多内容,LISP可以动态地重新定义语法,大概是宏.我好奇这到底有多远?你能重新定义语言结构,以至于它的边界成为另一种语言的编译器吗?例如,您是否可以将LISP的功能性质更改为更面向对象的语法和语义,或许可以说语法更接近像Ruby这样的东西?
特别是,是否可以使用宏来摆脱括号地狱?我已经学会了足够的(Emacs-)LISP来使用我自己的微功能定制Emacs,但我很好奇宏可以在定制语言方面走多远.
Eri*_*and 34
这是一个非常好的问题.
我认为这是微妙的,但绝对是可以回答的:
宏不会卡在s表达式中.有关使用关键字(符号)编写的非常复杂的语言,请参阅LOOP宏.因此,虽然您可以用括号开始和结束循环,但它内部有自己的语法.
例:
(loop for x from 0 below 100
when (even x)
collect x)
Run Code Online (Sandbox Code Playgroud)
话虽这么说,大多数简单的宏只使用s表达式.你会被"困住"使用它们.
但像塞尔吉奥所回答的那样,s表达开始感觉正确.语法不受影响,您可以在语法树中开始编码.
对于读者宏,是的,你可以想象写这样的东西:
#R{
ruby.code.goes.here
}
Run Code Online (Sandbox Code Playgroud)
但是你需要编写自己的Ruby语法解析器.
您还可以使用编译为现有Lisp构造的宏来模仿某些Ruby构造(如块).
#B(some lisp (code goes here))
Run Code Online (Sandbox Code Playgroud)
会翻译成
(lambda () (some lisp (code goes here)))
Run Code Online (Sandbox Code Playgroud)
请参阅此页面了解如何操作.
Sea*_*son 22
是的,您可以重新定义语法,以便Lisp成为编译器.您可以使用"Reader Macros"执行此操作,这与您可能正在考虑的常规"编译器宏"不同.
Common Lisp具有内置工具,可以为读取器和读取器宏定义新语法来处理该语法.此处理在读取时间(在编译或eval时间之前)完成.要了解有关在Common Lisp中定义阅读器宏的更多信息,请参阅Common Lisp Hyperspec - 您将要阅读Ch.2,"语法"和Ch.23,"读者".(我认为方案具有相同的设施,但我不熟悉它-看到计划来源为电弧的编程语言).
举个简单的例子,让我们假设您希望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 #\( #\[ )
Run Code Online (Sandbox Code Playgroud)
你告诉Lisp {就像一个(而且}就像一个).然后你创建一个函数(lcurly-brace-reader),只要它看到{,你就会调用它来调用{和你set-macro-character用来将该函数分配给{.然后你告诉Lisp(和)就像[和](也就是说,没有意义的语法).
您可以执行的其他操作包括,例如,创建新的字符串语法或使用[和]括起in-fix表示法并将其处理为S表达式.
您还可以远远超出此范围,使用您自己的宏字符重新定义整个语法,这些宏字符将触发阅读器中的操作,因此天空确实是极限.这只是Paul Graham和其他人一直说Lisp是编写编译器的好语言的原因之一.
Ser*_*sta 16
我不是Lisp专家,哎呀我甚至不是Lisp程序员,但经过一些语言实验后,我得出的结论是,一段时间后,括号开始变为'隐形',你开始看到代码为你想要它.您开始更多地关注通过s-exprs和宏创建的语法结构,而不是注意列表和括号文本的词法形式.
如果您利用一个有助于缩进和语法着色的好编辑器(尝试将括号设置为与背景非常相似的颜色),则尤其如此.
您可能无法完全替换语言并获得"Ruby"语法,但您不需要它.由于语言的灵活性,你可以找到一种方言,感觉就像你想要遵循'Ruby风格的编程'一样,无论那对你意味着什么.
我知道这只是一个经验观察,但我认为当我意识到这一点时,我有一个Lisp启蒙时刻.
jfm*_*fm3 15
一遍又一遍,Lisp的新手想要"摆脱所有的括号".它持续数周.没有任何项目可以在通常的S表达式解析器之上构建一个严格的通用编程语法,因为程序员总是最喜欢你当前认为的"括号地狱".它需要一点点习惯,但不是很多!一旦你习惯了它,你就可以真正体会到默认语法的可塑性,回到只有一种表达任何特定编程结构的方式的语言真的很光.
话虽这么说,Lisp是构建领域特定语言的绝佳基础.和XML一样好,如果不是更好的话.
祝好运!
Dan*_*reb 12
我见过的Lisp宏的最佳解释是
https://www.youtube.com/watch?v=4NO83wZVT0A
从大约55分钟开始.这是"实用公共Lisp"的作者Peter Seibel给出的一个视频,这是最好的Lisp教科书.
Lisp宏的动机通常难以解释,因为它们真的是在一个冗长的情况下出现在一个简单的教程中.彼得提出了一个很好的榜样; 你可以完全掌握它,它可以很好地正确使用Lisp宏.
你问:"你能否将LISP的功能性改变为更面向对象的语法和语义".答案是肯定的.事实上,Lisp最初根本没有任何面向对象的编程,因为Lisp在面向对象编程之前就已存在,所以并不奇怪!但是当我们在1978年第一次了解OOP时,我们能够轻松地将它添加到Lisp中,其中包括宏.最终开发了Common Lisp对象系统(CLOS),这是一个非常强大的面向对象编程系统,可以很好地适应Lisp.整个东西可以作为扩展加载 - 没有任何内置!这一切都是用宏完成的.
Lisp有一个完全不同的功能,称为"阅读器宏",可用于扩展语言的表面语法.使用读取器宏,您可以创建具有类似C或类似Ruby的语法的子语言.他们在内部将文本转换为Lisp.大多数真正的Lisp程序员并没有广泛使用它们,主要是因为很难扩展交互式开发环境以理解新语法.例如,Emacs缩进命令会被新语法混淆.但是,如果你精力充沛,Emacs也是可扩展的,你可以教它新的词法语法.
Luí*_*ira 11
常规宏对对象列表进行操作.最常见的是,这些对象是其他列表(因此形成树)和符号,但它们可以是其他对象,如字符串,哈希表,用户定义的对象等.这些结构称为s-exps.
因此,当您加载源文件时,您的Lisp编译器将解析文本并生成s-exps.宏对这些进行操作.这非常有用,它是在s-exps精神范围内扩展语言的绝佳方式.
此外,上述解析过程可以通过"读取器宏"进行扩展,使您可以自定义编译器将文本转换为s-exps的方式.但是,我建议您接受Lisp的语法,而不是将其弯曲成其他内容.
当你提到Lisp的"功能性"和Ruby的"面向对象语法"时,你听起来有点困惑.我不确定应该是什么"面向对象的语法",但Lisp是一种多范式语言,它极其支持面向对象的编程.
顺便说一下,当我说Lisp时,我指的是Common Lisp.
我建议你放弃偏见,给Lisp一个诚实的去.
小智 10
括号地狱?我看到没有更多的括号:
(function toto)
Run Code Online (Sandbox Code Playgroud)
比在:
function(toto);
Run Code Online (Sandbox Code Playgroud)
并在
(if tata (toto)
(titi)
(tutu))
Run Code Online (Sandbox Code Playgroud)
不超过:
if (tata)
toto();
else
{
titi();
tutu();
}
Run Code Online (Sandbox Code Playgroud)
我看到更少的括号和';' 虽然.
是的,你可以从根本上改变语法,甚至逃避"括号地狱".为此,您需要定义新的阅读器语法.查看读者宏.
但我确实怀疑要达到Lisp专业知识的水平来编程这样的宏,你需要让自己沉浸在语言中,以至于你不再考虑括号"地狱".即当你知道如何避免它们时,你会接受它们作为一件好事.