成为Lisp的新手我想知道Lisp语法是否可以“修复”?
有人说Lisp中的语法是它最大的优势之一。我不太明白这一点。
是不是可以用白色空格,新行和缩进的组合替换“明显”的括号?就像在Python中一样?
在我看来,括号是Lisp代码中使用最多的字符。我想知道这是否属实 - 但如果是,这不是一个建议,语法中有一些冗余吗?
这个问题有一些简单的答案 - 为什么这么多括号?
例如:
(defun factorial (x)
(if (= x 0)
1
(* x
(factorial (- x 1)))))
为什么不:
defun factorial (x)
if (= x 0)
1
* x
factorial
- x 1
e.g。在行尾用括号括起来,并始终在新行上打开它们。 只有1是模棱两可的 - 是1还是(1) - 但是我们可以引入一个例外 - 单个标记不是“分层”。
这可行吗?
编辑:
答案 0 :(得分:29)
一旦编写了几个宏,你就会改变主意。
答案 1 :(得分:27)
已经做了很多次(一个<二十行预处理器会做奇迹)。但是将它们明确化也是有利的。它将代码和数据之间的并行性带回家,并以某种方式引导您走出让您觉得烦恼的想法。
你可以(对于一个类似的例子)采用面向对象的语言并将所有方法的语法分组移除到类中(因此它们实际上变成了重载函数)。这会让你更直观地看待它,但是也会丢失一些东西。
当你看到口齿不清时,你应该认为“一切都是一个清单。嗯”
(好吧,好吧,“嗯”是可选的)。
答案 2 :(得分:17)
“也许这个过程应该被视为Lisp黑客的成年礼。”
- Steele和Gabriel,“Lisp的演变”,1993年
答案 3 :(得分:12)
您的建议似乎已在 Lispin
修改: sindikat在下面的评论中指出该链接不再有效。以下是网络存档中网站的最后一个有效版本:http://wayback.archive.org/web/20080517144846id_/http://www.lispin.org/
答案 4 :(得分:9)
我曾多次在其他语言中比较Lisp代码和等效代码。 Lisp代码有更多的parens,但是如果你用其他语言计算所有分组字符[] {}(),那么Lisp比所有这些都少。它并不冗长:它更加一致!
从这个角度来看,“问题”只是Lisp使用一种类型的构造(列表)来处理所有事情。这是它的宏,它的对象系统,它的几个最强大的循环结构的基础,等等。你认为是一个小的风格问题(括号看起来更酷?可能)实际上是语言能力的标志。
那就是说,Lisp就是为程序员赋权。如果你愿意,可以编写自己的方言,让你这样做。 Lisp(不像我能提到的一些语言!)是关于程序员的力量,所以使用它。如果你可以使它工作,也许它会起飞。我认为不会,但没有什么可以阻止你尝试,你会学到很多东西。
答案 5 :(得分:6)
lisp“语法”的意义在于它不存在。 s表达式是一个身份树,其中树结构由parens(和缩进)表示。值得注意的是,性别仅仅是一种低级别的代表,但最终人们更喜欢它并继续使用它。
表达式对lisp中的执行引擎意味着非常灵活意味着上下文敏感。
在其他语言中,上下文敏感度级别要低得多,并且可用于构建自己的抽象的构建块集不太可自由扩展。因此,表示少数给定结构的特殊语法符合图片。
在lisp中,我可以改变一切的含义,即使是以上下文敏感的方式。对于一些预定义的构造具有特殊语法将是愚蠢的,因为我可能最终使用我自己的“if”,或者我自己的专用闭包等。如果我的新“if”需要4个参数(例如,如果是程序并告诉某些团队在某些情况下总是失败或成功)?我应该如何扩展预定义'if'的语法?使用AST(sexps)要容易得多,但为什么还要特别使用特殊语法?
另请注意,使用像emacs这样的编辑器可以非常轻松地以结构化方式编辑这样的树。例如,拥有一个键来转换树中的两个节点对于交换变量声明和交换程序块中的两个语句同样有用(提示:这就是为什么“额外”的parens在let,cond等中有用)。
所以,这就是为什么 lisp的非语法的原因所以吸引那些习惯于扩展语言而不是弯曲问题的人适合一组预定义的工具......但这并不意味着语法糖不会用于用户给定的结构!
我们使用的用户定义语法的一些示例:
[]
个parens,你不想命名闭包的变量<xml >
语法,用于在lisp代码中内联xhtml生成(请注意,此语法由用户库提供,它可以是以上下文敏感的方式启用)答案 6 :(得分:5)
它可以工作。它被称为Dylan。
答案 7 :(得分:5)
即使是Paul Graham,Lisp语系家族的声音倡导者,也从他自己的方言Arc中删除了一些括号:
Lisp黑客的注意事项:如果你习惯了传统的Lisp
cond
运算符,如果相同,则相同,但更少 括弧。 E.g。(cond (a b) (c d) (t e))
变为
(if a b c d e)
(来自Arc Tutorial)
答案 8 :(得分:3)
有两种人物:那些通过内置堆叠机器处理信息的人,以及那些以大块或块状物消费信息的人。这些群体彼此互不相容;他们阅读不同的书籍,有不同的写作风格,最重要的是,用不同的编程语言编写代码。我属于第二组;但是,我认识第一组的许多程序员。
对于第一组中的人来说,嵌套子句和子条款绝对没有错;他们自然地掌握递归;他们慢慢地看着代码,逐个语句,一行一行,并在他们的大脑中堆叠机器在潜意识层面上计算括号和圆括号。 Lisp语法对他们来说很自然。地狱,他们可能发明了堆栈机器和Forth语言。但是要告诉他们,比方说,Python(哦,不!),他们会无助地看一瞥代码,无法理解为什么这些愚蠢的代码块保持打开,没有匹配的结束语句。
对于我们来说,第二组中的穷人,没有其他选择,只有组代码语句进入块,并在视觉上缩进它们。我们期待屏幕填充代码,首先注意大规模结构,然后单独的函数或方法,然后在这些方法中的语句组,然后是行和语句,从上到下。我们不能线性思考;我们需要视觉界限和清洁缩进政策。因此,我们不能屈服于使用Lisp;对我们来说,这是一个不规则的关键词和愚蠢的括号。
大多数编程语言都兼容两种思维方式(那些“块”是有理由的)。值得注意的例外是Lisp和Forth,它们只是第一组,而Python只是第二组。如果你属于第二组,我认为你不需要让Lisp适应你的思维方式。如果您仍需要功能语言,请尝试Haskell。它是一种功能性语言,专为那些以块而非堆栈思考的人而设计。
答案 9 :(得分:1)
回答原因:
据我所知,它的主要用途是可读性,因此查看代码的人可以更轻松地解读它。
希望它有所帮助。
答案 10 :(得分:1)
我个人对此的看法是:不要使用换行符和缩进作为“隐式”分隔符(我也不喜欢按运算符优先级进行隐式分组,但这是一个不同的,虽然是相关的主题)。
示例:这是有效的Python吗?它符合您的期望吗?
if foo < 0 :
bar
else :
baz
quuz
我有一个小提议:我们可以使用预处理器自动缩进Python代码,方法是在代码中加入特殊字符,告诉它语句的开始和结束位置。这个括号怎么样?
答案 11 :(得分:1)
这个帖子已经过时了,但我决定投入,因为我创建了一个非常相似的reader system。
编辑:一些使用样本:
!defun fact (n) if (zerop n) 1 * n fact (1- n)
!defun fact !n if !zerop n 1 !* n !fact !1- n
有关更多信息,请查看项目的主页。
答案 12 :(得分:0)
通过链接阅读,我找到了这个 - Indentation-sensitive syntax - 还有Guile模块,它实现了这种语法,所以可以直接尝试它。
答案 13 :(得分:0)
你可以看看Clojure。较小的括号,但要记住更多的语法。
答案 14 :(得分:0)
我已经尝试并编写了几个依赖缩进的语法。在最好的结果中,整个语法改变了它的本质,因此语言已经从一个转向另一个。好的基于缩进的语法不再适用于lisp。
为缩进赋予句法意义的麻烦不会从白痴和\ t与空白辩论中产生。标记化既不是一个麻烦,因为读取换行符和空格不应该比其他任何东西更难。最难的是确定缩进应该出现在哪里,以及如何在不对语言进行过于复杂的语法的情况下为其添加含义。
我开始考虑使用一些聪明的编程来最小化括号数量时,原始的lisp样式语法会更好。这可以在当前的lisp实现中完成,但在将来的lisp实现中,它可以更容易地完成。当只需要标记几个规则时,解析起来既快速又简单,而且根本没有解析。
答案 15 :(得分:0)