修复 Lisp 语法
作为 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
例如,在行尾关闭括号,并始终在新行中打开它们。 只有 1 是不明确的 - 是 1 还是 (1) - 但我们可以引入一个例外 - 单个标记不会“列出”。
这行得通吗?
编辑:
谢谢大家! 我现在看到 lispin 链接 //www.lispin.org" rel="noreferrer">网站。
Being a newbie to Lisp I'm wondering if the Lisp syntax could be "fixed"?
Some people say the syntax in Lisp is one of its biggest strengths. I don't quite understand this.
Isn't it possible to replace "obvious" parentheses with a combination of white spaces, new lines and indenting? Just like in Python?
It looks to me like parentheses are the most used characters in Lisp code. I'm wondering if that's true - but if it is, isn't this a suggestion, that there is some redundancy in the syntax?
Is there some simple answer to the question - why so many parentheses?
For example:
(defun factorial (x)
(if (= x 0)
1
(* x
(factorial (- x 1)))))
Why not:
defun factorial (x)
if (= x 0)
1
* x
factorial
- x 1
e.g. close parentheses at the end of line, and always open them on new lines.
Only the 1 would be ambiguous - is it 1 or (1) - but we could introduce an exception - single tokens are not "listified".
Could this work?
Edit:
Thank you all! I see now there are some links at the lispin site.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
回答为什么的问题:
据我所知,它的主要用途是可读性,以便查看代码的人可以更轻松地破译它。
希望能帮助到你。
To answer the question of why:
It's main use as far as i know is readability, so that people who look at your code can decipher it more easily.
Hope it helps.
通过阅读链接,我发现了这个 - 缩进敏感语法 - 还有Guile模块,实现了这个语法,所以可以直接尝试一下。
可以找到一种很有前途的 Lisp 方言 (Arc) 此处。 (我想应该先看一些真实的代码看看感觉如何)
Reading through the links, I found this one - Indentation-sensitive syntax - there is also Guile module, that implements this syntax, so one could directly try it.
A quite promising Lisp dialect (Arc) could be found here. (I guess one should first some real code see how it feels)
我个人对此的看法是:不要使用换行符和缩进作为“隐式”分隔符(我也不喜欢按运算符优先级进行隐式分组,但这是一个不同但相关的主题)。
示例:这是有效的 Python 吗? 它符合您的预期吗?
我有一个小建议:我们可以使用预处理器自动缩进 Python 代码,方法是将特殊字符放入代码中,告诉它语句的开始和结束位置。 这个的括号怎么样?
My personal opinion on this is: don't use newlines and indentation as "implicit" separators (I also don't like implicit grouping by operator precedence, but that is a different, although related topic).
Example: Is this valid Python? Does it do what you expect?
I have a little proposal: we could use a preprocessor to indent Python code automatically, by putting special characters into the code that tell it where a statement begins and ends. How about parentheses for this?
你可以看看 Clojure。 括号更少,但要记住的语法更多。
You could take a look at Clojure. Lesser parentheses but more syntax to remember.
我已经尝试并编写了几种依赖缩进的语法。 最好的结果是,整个语法已经改变了它的本质,因此语言已经从一种语言转变为另一种语言。 良好的基于缩进的语法已经不再接近 lisp 了。
为缩进赋予语法意义的麻烦并不是由白痴和 \t 与空白的争论引起的。 标记化也不是问题,因为读取换行符和空格不应该比其他任何事情都困难。 最困难的事情是确定缩进在出现的位置应该意味着什么,以及如何在不使语言语法过于复杂的情况下为其添加含义。
我开始认为,当你通过一些巧妙的编程来最小化括号的数量时,原始的 lisp 风格语法毕竟更好。 这可以做到,但在当前的 lisp 实现中并不那么容易,但在未来的 lisp 实现中可以更容易地完成。 当您只需标记几条规则并且几乎不需要解析时,解析起来既快速又简单。
I've tried out and written couple of syntaxes that rely on indentation. At the best results the whole syntax has changed it's nature and therefore the language has turned from one to another. Good indentation-based syntax isn't anything near lisp anymore.
The trouble of giving syntactic meaning for indentation doesn't rise from the idiots and \t vs. whitespace debating. Tokenizing is neither a trouble since reading newlines and spaces shouldn't be harder than anything else. The hardest thing is to determine what indentation should mean where it appears, and how to add meaning to it without making too complicated syntax for the language.
I am starting to consider original lisp style syntax is after all better when you minimize the amount of parenthesis with some clever programming. This can be done, not so easily in current lisp implementations, but in future lisp implementations it can be done easier. It's fast and simple to parse when there's only couple of rules you have to tokenize, and nearly no parsing at all.
这个线程很旧,但我决定做出贡献,因为我创建了一个非常相似的 阅读器系统< /a>.
编辑:一些使用示例:
有关更多信息,请查看项目的主页。
This thread is old, but I've decided to contribute, because I've created a very similar reader system.
EDIT: Some samples of usage:
For more information check the homepage of project.
有一个 备用球拍语法。
读作
There is an alternate Racket Syntax.
reads as
一旦你编写了几个宏,你就会改变主意。
You'll change your mind once you write a couple of macros.
它已经被做过很多次了(一个<20行的预处理器将创造奇迹)。 但将它们明确化也有一个优点。 它让您了解代码和数据之间的并行性,并在某种程度上引导您摆脱让您觉得它们烦人的思维。
您可以(举一个类似的例子)采用面向对象的语言,并将所有方法的语法分组删除到类中(因此它们实际上变成了重载函数)。 这会让你更多地像看待直接的命令式语言一样看待它,但也会丢失一些东西。
当您查看 lisp 时,您应该会想到“一切都是列表。Ommm”
(好吧,“Ommm”是可选的)。
It's been done lots of times (a < twenty line preprocessor will do wonders). But there is also an advantage to having them explicit. It drives home the parallelism between code and data, and in a way leads you out of the sort of thinking that makes you find them annoying.
You could (for an analogous example) take an object oriented language and remove all the syntactic grouping of methods into classes (so they became, in effect, overloaded functions). This would let you look at it more as you would a straight imperative language, but something would be lost as well.
When you look at lisp you're supposed to think "Everything is a list. Ommm"
(Well, Ok, the "Ommm" is optional).
“也许这个过程应该被视为 Lisp 黑客的成人礼。”
——Steele 和 Gabriel,《Lisp 的进化》,1993 年
"Perhaps this process should be regarded as a rite of passage for Lisp hackers."
-- Steele and Gabriel, "The Evolution of Lisp", 1993
您的建议似乎已在
Lispin中实现编辑:< /strong> sindikat 在下面的评论中指出该链接不再有效。 以下是网络档案馆中该网站的最新有效版本: http://wayback.archive.org/web/20080517144846id_/http://www.lispin.org/
What you suggest appears to have been implemented in
LispinEdit: sindikat points out in the comments below that the link is no longer valid. Here's the last valid version of the site from the Web Archive: http://wayback.archive.org/web/20080517144846id_/http://www.lispin.org/
我曾多次比较 Lisp 代码和其他语言的等效代码。 Lisp 代码有更多的括号,但是如果计算其他语言中的所有分组字符 []{}(),Lisp 的括号比所有这些都少。 它不是更冗长:而是更一致!
从这个角度来看,“问题”很简单,就是 Lisp 对所有事情都使用一种类型的构造(列表)。 这是它的宏、对象系统、几个最强大的循环结构等等的基础。 你所认为的小风格问题(括号看起来会更酷吗?可能)实际上是语言力量的标志。
也就是说,Lisp 就是赋予程序员权力。 如果您愿意,可以编写自己的方言来实现此目的。 Lisp(与我提到的某些语言不同!)完全取决于程序员的能力,所以使用它。 如果你能让它发挥作用,也许它会起飞。 我认为不会,但是没有什么可以阻止你尝试,而且无论哪种方式你都会学到很多东西。
Several times I've compared Lisp code and equivalent code in other languages. Lisp code has more parens, but if you count all grouping characters []{}() in other languages, Lisp has fewer parens than all these. It's not more verbose: it's more consistent!
When seen from this point of view, the "problem" is simply that Lisp uses one type of construct (lists) for everything. And this is the basis for its macros, its object system, a couple of its most powerful looping constructs, and so on. What you see as a minor style issue (would brackets look cooler? probably) is actually a sign of language power.
That said, Lisp is all about giving power to the programmer. If you want, write your own dialect that lets you do this. Lisp (unlike some languages I could mention!) is all about programmer power, so use it. If you can make it work, maybe it'll take off. I don't think it will, but there's nothing to stop you from trying, and you'll learn a lot either way.
lisp“语法”的要点在于它不存在。 s-表达式是恒等树,其中树结构由括号(和缩进)表示。 值得注意的是,sexp 本来只是一种低级的表示,但人们最终更喜欢它并继续使用它。
表达式对执行引擎的意义在 lisp 中非常灵活,而且它上下文敏感。
在其他语言中,上下文敏感程度为低得多,并且您可以用来构建自己的抽象的构建块集的可自由扩展性要差得多。 因此,表示少数给定结构的特殊语法正适合这种情况。
在 lisp 中,我可以改变一切的含义,即使是以上下文敏感的方式。 对一些预定义的构造使用特殊的语法是愚蠢的,因为我最终可能会使用我自己的“if”,或者我自己的专门闭包等。如果我的新“if”需要 4 个参数(例如,将某个 if 进行分组)怎么办?编程并告诉某些团体在某些情况下总是失败或成功)? 我应该如何扩展预定义“if”的语法? 求助于 AST(sexp)要容易得多,但是为什么还要费心使用特殊语法呢?
另请注意,使用 emacs 这样的编辑器可以非常轻松地以结构化方式编辑此类树。 例如,使用一个键来转置树中的两个节点对于交换变量声明和交换程序块中的两个语句同样有用(提示:这就是为什么“额外”括号在 let、cond 等中很有用)。
因此,这就是为什么 lisp 的非语法如此吸引了许多习惯于扩展语言的想法的人,而不是将问题扭曲以适应特定的语言。预定义的工具集...但这并不意味着语法糖不用于用户给定的构造!
我们使用的用户定义语法的一些示例:
[]
括号,您不想命名闭包的变量
语法lisp 代码(请注意,此语法由 user 库提供,并且可以以上下文相关的方式启用)The point of lisp "syntax" is its non-existence. An s-expression is a tree of identities, where the tree structure is denoted by parens (and indentation). It's worth noting that sexps were meant to be a low-level representation only, but people ended up liking it more and kept using it.
What an expression means to the execution engine is incredibly flexible in lisp and it's also context sensitive.
In other languages, the level of context sensitivity is much lower and the set of building blocks you can use to build your own abstractions is much less freely extensible. Therefore, special syntax denoting the few given constructs is fitting the picture.
In lisp, I can change the meaning of everything, even in a context sensitive manner. Having special syntax for a few predefined constructs would be silly because I may end up using my own 'if', or my own specialized closures, etc.. What if my new 'if' needs 4 arguments (e.g. to group certain if's of a program and tell some groups to always fail or succeed in certain situations)? How should I extend the syntax of the predefined 'if'? It's much easier to resort to the AST (sexps), but then why bother with special syntax at all?
Also note that using an editor like emacs makes it very easy to edit such a tree in a structured way. For example, having a key to transpose two nodes in a tree is equally useful to swap variable declarations and to swap two statements in a program block (hint: that's why the "extra" parens are useful in let, cond, etc.).
So, that's the reasoning why the non-syntax of lisp is so appealing to many people who got used to the idea of extending the language instead of bending the problem to fit a predefined set of tools... but it doesn't mean that syntax sugar is not used for user-given constructs!
Some examples of user defined syntax that we use:
[]
parens used for tiny closures where you don't want to name the closure's variables<xml >
syntax to inline the xhtml generation in lisp code (please note that this syntax is provided by a user library, and it can be enabled in a context sensitive manner)它可以工作。 它的名称为 Dylan。
It could work. It's called Dylan.
甚至 Lisp 语言家族的大力倡导者 Paul Graham 也从他自己的方言中删除了一些括号< a href="http://www.paulgraham.com/arc.html" rel="nofollow noreferrer">弧:
(来自 Arc 教程)
Even Paul Graham, a vocal advocate for the Lisp family of languages, has removed some parentheses from his own dialect Arc:
(from the Arc Tutorial)
有两种人™:通过大脑中内置的堆栈机器处理信息的人,以及大块或块地消费信息的人。 这些群体彼此不相容; 他们阅读不同的书籍,有不同的写作风格,最重要的是,用不同的编程语言编写代码。 我属于第二类; 然而,我认识许多来自第一组的程序员同事。
对于第一类人来说,嵌套子句绝对没有问题; 他们自然地掌握了递归; 他们慢慢地、逐条语句、逐行地查看代码,大脑中的堆栈机在潜意识层面不断计算大括号和括号。 Lisp 语法对他们来说非常自然。 天啊,他们可能发明了堆栈机和 Forth 语言。 但是向他们展示Python(哦,不!),他们会无助地浏览代码表,无法理解为什么这些愚蠢的代码块保持开放,没有匹配的结束语句。
对于我们这些第二组中的可怜人来说,除了将代码语句分组到块中并在视觉上缩进它们之外,没有其他选择。 我们看着充满代码的屏幕,首先注意到大规模的结构,然后是单独的函数或方法,然后是这些方法中的语句组,然后是行和语句,从上到下。 我们不能线性思考; 我们需要视觉边界和干净的缩进政策。 因此,我们不能屈服于 Lisp 的工作。 对我们来说,这是一堆不规则的关键字和愚蠢的括号。
大多数编程语言都兼容这两种思维方式(这些“障碍”的存在是有原因的)。 值得注意的例外是 Lisp 和 Forth(仅属于第一组)和 Python(仅属于第二组)。 如果你属于第二类,我认为你不需要让 Lisp 适应你的思维方式。 如果您仍然需要函数式语言,请尝试 Haskell。 它是一种函数式语言,专为那些以块而非堆栈方式思考的人而设计。
There are two kinds of people™: those who process information by means of built-in stack machine in their brains, and those who consume it in large chunks or blocks. These groups are mutually incompatible with each other; they read different books, have different writing styles and, most importantly, write code in different programming languages. I belong to the second group; however, I know many fellow programmers from the first group.
For people in the first group, there is absolutely nothing wrong with nested clauses and subclauses; they grasp recursion naturally; they look at the code slowly, statement by statement, line by line, and stack machine in their brains keeps counting braces and parentheses at the subconscious level. Lisp syntax is quite natural to them. Hell, they probably invented stack machines and Forth language. But show them, say, Python (oh noes!), and they will glance helplessly to sheets of code, unable to understand why these stupid code blocks are left open, with no matching closing statements.
For us, poor guys in the second group, there is no other option but group code statements into blocks, and visually indent them. We look to screen filled with code, first noticing large-scale structure, then separate functions or methods, then statements groups within these methods, then lines and statements, from top to bottom. We cannot think linearly; we need visual boundaries and clean indentation policies. Hence, we cannot bend ourselves to work with Lisp; for us, it is an irregular mess of keywords and silly parentheses.
Most programming languages are compatible with both ways of thinking (those "blocks" are there for reason). Notable exceptions are Lisp and Forth, which are first group only, and Python, which is second group only. I don't think you need to adapt Lisp to your way of thinking if you belong to the second group. If you still need a functional language, try Haskell. It is a functional language designed for people who think in blocks, not stacks.