逸之

V1

2022/01/11阅读:54主题:红绯

why lisp

Why Racket? Why Lisp?

为什么是 Racket? 为什么是 Lisp?

Beau­tiful Racket and Prac­tical Typog­raphy were made possible by a publishing system called Pollen. I created Pollen with the Racket program­ming language. Racket is a descen­dant of Scheme, which in turn is a descen­dant of Lisp.

美丽的球拍和实用的字体是由一个叫做花粉的出版系统创造的。我用 Racket 编程语言创建了 Pollen。Racket 是 Scheme 的后代,而 Scheme 又是 Lisp 的后代。

So while Racket is not Lisp (in the specific Common Lisp sense), it is a Lisp (in the familial sense). Its core ideas—and core virtues—are shared with Lisp. So talking about Racket means talking about Lisp.

因此,尽管 Racket 不是 Lisp (在特定的 Common Lisp 意义上) ,但它是一个 Lisp (在家族意义上)。它的核心思想和核心优点都与 Lisp 共享。所以谈论 Racket 就意味着谈论 Lisp。

In prac­tical program­ming projects, Lisps are rare. Racket espe­cially so. Thus, before I orig­i­nally embarked on my Lisp adven­ture, I wanted to under­stand the costs & bene­fits of using a Lisp. Why do Lisps have such a great repu­ta­tion, yet few users? Was I seeing some­thing everyone else missed? Or did they know some­thing I didn’t? To find out, I read what­ever I could find about Lisps, including Paul Graham’s Hackers & Painters and Peter Seibel’s Prac­tical Common Lisp. (OK, parts. It’s a big book.)

在实际的编程项目中,lisp 是很少见的。特别是球拍。因此,在开始我的 Lisp 之旅之前,我想了解使用 Lisp 的成本和好处。为什么 lisp 有如此好的声誉,却很少有用户?我是不是看到了别人都没看到的东西?还是他们知道一些我不知道的事?为了找到答案,我阅读了所有我能找到的关于 Lisp 的东西,包括 Paul Graham 的《 Hackers & Painters 》和 Peter Seibel 的《 Practical Common Lisp 》。(好的,零件。这是一本大书。)

What I found was plenty of Lisp flat­tery from expert Lisp program­mers. (Also plenty of Lisp kvetchery from its detrac­tors.) What I didn’t find were simple, persua­sive argu­ments in its favor. So here’s why Racket was the right tool for me, and what I see as the prac­tical virtues of Lisps in general.

我发现大量 Lisp 程序员的奉承话。(也有很多 Lisp 的批评者)我没有发现的是对它有利的简单而有说服力的论据。所以,这就是为什么 Racket 对我来说是正确的工具,以及我所看到的 lisp 的实用优点。

Consider the source 考虑一下来源

I didn’t study computer science in college (though I was a math major for two years, before switching to design). I’ve never held an offi­cial job as a programmer. Rather, program­ming has been a secondary skill I’ve used in my work as a web designer, type designer, and writer.

我在大学里没有学过计算机科学(虽然我在转学设计之前主修了两年数学)。我从来没有做过程序员这样的正式工作。相反,编程一直是我作为网页设计师、字体设计师和作家工作中使用的次要技能。

But in the last few years, I’ve spent an increasing amount of my time program­ming. This program­ming gener­ates income. So by the simplest defi­n­i­tion—does the skill make you money?—I suppose I qualify as a profes­sional programmer. And since most of my program­ming efforts are in Racket, I qualify as a profes­sional Racket programmer.

但是在过去的几年里,我花在编程上的时间越来越多。这个程序产生收入。因此,按照最简单的定义ーー技能能让你赚钱吗? ーー我想我符合专业程序员的资格。因为我的大部分编程工作都在 Racket,所以我有资格成为一个专业的 Racket 程序员。

Mind you, I’m not claiming that I’m an expert programmer. Among the Racket commu­nity, which is laden with computer-science Ph­Ds & profes­sors, I (have no choice but to) embrace my rela­tive inex­pe­ri­ence. Hence the title of my talk at Racket­Con 2014: Like a Blind Squirrel in a Ferrari.

请注意,我并不是说我是一个专业的程序员。在充斥着计算机博士和教授的 Racket 社区中,我(别无选择)接受了我相对缺乏的经验。因此,我在2014年 RacketCon 大会上的演讲题目是: 像一只开着法拉利的瞎松鼠。

Yet despite my limi­ta­tions as a programmer, with Racket I’ve been able to render bigger ideas into programs more quickly, and with fewer bugs, than any language I’ve used before (and there have been many—BASIC, C, C++, Perl, Java, Java­Script, Python, and others). Since I haven’t gotten a brain trans­plant recently, there must be some­thing special about Racket as a language.

然而,尽管我作为一个程序员有局限性,但是使用 Racket,我能够比我以前使用过的任何语言更快地将更大的想法转换成程序,并且有更少的 bug (有很多语言ー basic、 c、 c + + 、 Perl、 Java、 JavaScript、 Python 等等)。既然我最近没有接受脑部移植,那么 Racket 作为一种语言一定有什么特别之处。

If you’re not familiar with Lisp如果你不熟悉 Lisp

Lisp is a language most program­mers have heard of, for two reasons. First, it’s one of the oldest computer languages, in use since 1958. Second, it’s accrued a repu­ta­tion as a language for brainiacs. Orig­i­nally this repu­ta­tion arose from its asso­ci­a­tion with the field of arti­fi­cial intel­li­gence. Since then, this repu­ta­tion has been main­tained by peri­odic endorse­ments from respected program­mers (latterly, Eric Raymond and Paul Graham) and the enduring fame of the text­book used in intro­duc­tory computer-science courses at MIT, Struc­ture and Inter­pre­ta­tion of Computer Programs (which uses Scheme, and that one I did read start to finish).

Lisp 是一种大多数程序员都听说过的语言,原因有二。首先,它是自1958年以来最古老的计算机语言之一。其次,它逐渐被认为是聪明人的语言。最初,这种声誉来自于它与人工智能领域的联系。从那时起,这种声誉得到了一些有名的程序员(后来,Eric Raymond 和 Paul Graham)的定期认可,以及麻省理工学院计算机科学入门课程中使用的教科书的持久声誉(该课程使用 Scheme,而我确实从头到尾读完了这本计算机程序的构造和解释)。

But as main­stream program­ming tools, Lisp and its descen­dants have been largely ignored. Popu­larity of program­ming languages is tricky to measure, but here’s a simple proxy—let’s count the number of projects currently hosted on Git­Hub. One could quibble about the accu­racy of this method, except that the results aren’t even close:

但是作为主流的编程工具,Lisp 及其后代在很大程度上被忽视了。编程语言的流行程度难以衡量,但这里有一个简单的代理ーー让我们来计算一下目前托管在 GitHub 上的项目数量。人们可以对这种方法的准确性吹毛求疵,只是结果远非如此:



Language 语言 Git­Hub projects 项目
JavaScript 2\. JavaScript 7,488,087
Java 爪哇 6,570,575
Python 巨蟒 4,017,958
PHP 2,123,489
Ruby 露比 1,699,590
Clojure 64,239
Lisp 17,989
Scheme 计划 12,412
Racket 球拍 11,725

The last four languages are Lisps, and together account for only 106,365 projects. Racket itself only accounts for a small frac­tion of this small frac­tion.

最后四种语言是 lisp,加起来只有106,365个项目。球拍本身只占这一小部分的一小部分。

Popular program­ming languages aren’t neces­sarily good—look what’s at the top of that list.  + [Java­Script] has a lot of stupid in it … The good parts of [Java­Script] go back to Scheme and Self.
—Brendan Eich, here and here But unpop­ular languages often have fatal flaws that prevent wider adop­tion. As I was consid­ering languages, Racket had a lot to recom­mend it. But was there a fatal flaw I was over­looking? And by commit­ting to a Lisp, would I be painting myself into a corner? I wanted to under­stand the risks and bene­fits.

流行的编程语言并不一定是好的ーー看看排在前面的是什么。但是不受欢迎的语言往往有致命的缺陷,阻碍了更广泛的应用。当我在考虑语言的时候,Racket 有很多值得推荐的地方。但是我忽略了一个致命的缺陷吗?如果我使用 Lisp 语言,我会把自己逼到一个角落吗?我想了解其中的风险和好处。

Flat­tery gets you nowhere 奉承对你没有好处

I said above that Lisp flat­tery is easy to find. The problem with Lisp flat­tery is that it makes sense only to expe­ri­enced Lisp program­mers. To others—espe­cially those who are trying to decide whether to learn and use a Lisp—it just comes across as unsub­stan­ti­ated hoodoo.

我上面说过,口齿不清的恭维话很容易找到。Lisp 奉承的问题在于,它只对有经验的 Lisp 程序员有意义。对于其他人来说,尤其是那些试图决定是否学习和使用 lisp 的人来说,它只是一个没有根据的巫术。

For example, in his essay How to Become a Hacker, Eric Raymond says “Lisp is worth learning for … the profound enlight­en­ment expe­ri­ence you will have when you finally get it. That expe­ri­ence will make you a better programmer for the rest of your days, even if you never actu­ally use Lisp itself a lot.” Unfor­tu­nately Raymond doesn’t follow up this claim by describing the “enlight­en­ment expe­ri­ence”, nor why it’s “profound”, nor how it will improve your program­ming skills gener­ally.

例如,埃里克 · 雷蒙德在他的文章《如何成为一名黑客》中说: “ Lisp 是值得学习的... ... 当你最终获得它时,你将获得深刻的启蒙体验。这种经历会让你在以后的日子里成为一个更好的程序员,即使你实际上从来没有经常使用过 Lisp。”不幸的是,雷蒙德并没有继续这个主张,描述“启蒙体验”,也没有解释为什么它是“深刻的”,也没有解释它将如何提高你的编程技能。

To be fair, Raymond’s essay is not focused on Lisp. But compare Beating the Aver­ages, by Paul Graham, which is. Graham starts off by citing Raymond’s compli­ment to Lisp and seems ready to make the claim concrete.

公平地说,Raymond 的文章并没有关注 Lisp。但是比较一下保罗 · 格雷厄姆的《超越平均值》。格雷厄姆首先引用了雷蒙德对 Lisp 的赞美,并且似乎已经准备好要求具体化。

Instead, he breaks it into smaller chunks of flat­tery. “We knew Lisp was a really good language for writing soft­ware quickly.” Because of what char­ac­ter­is­tics? He doesn’t say, but then describes Lisp as his “secret weapon”. OK, so what’s the secret? He says “program­ming languages vary in power”. Fine, but what exactly makes Lisp more powerful?

相反,他把它分成小块的奉承话。“我们知道 Lisp 是一种非常好的编写软件的语言。”因为什么特征?他没有说,但随后将 Lisp 描述为他的“秘密武器”。好吧,那么秘诀是什么呢?他表示,“编程语言的能力各不相同”。好吧,但是到底是什么让 Lisp 变得更强大呢?

Graham offers one concrete example: Lisp’s macro facility, which he describes as its ability to make “programs that write programs”. After four years using a Lisp language, I’d agree with Graham that macros are great when you need them. But for someone new to Lisp languages, they’re not neces­sarily a bread-and-butter benefit.

Graham 举了一个具体的例子: Lisp 的宏工具,他将其描述为“编写程序的程序”的能力。在使用 Lisp 语言四年之后,我同意 Graham 的观点: 当你需要宏的时候,它们是非常棒的。但对于初学 Lisp 语言的人来说,它们并不一定是基本的好处。

I was hopeful when I opened Peter Seibel’s Prac­tical Common Lisp and saw that the intro­duc­tion was subti­tled “Why Lisp?” Yes, tell me! Seibel echoes Graham’s claim: “You’ll get more done, faster, using [Lisp] than you would using pretty much any other language.” OK, but how? Seibel wonders whether “I like Lisp because of some quirk in the way my brain is wired. It could even be genetic, since my dad has it too.” That’s not encour­aging to those of us outside your family. Ulti­mately, he sums up the appeal of Lisp by describing it as “the program­mable program­ming language”. But I’ve never used a program­mable program­ming language. Why should I start?

当我打开 Peter Seibel 的《实用公共 Lisp 》 ,看到序言的副标题是“为什么 Lisp?”时,我满怀希望是的,告诉我!Seibel 回应了 Graham 的说法: “使用[ Lisp ]比使用几乎任何其他语言都能做得更多、更快。”好吧,但是怎么做呢?塞贝尔想知道“我喜欢 Lisp 是不是因为我的大脑连接方式有些怪异。这甚至可能是遗传的,因为我爸爸也有这种病。”这对你家庭以外的人可不是什么好消息。最后,他总结了 Lisp 的吸引力,将其描述为“可编程编程语言”。但是我从来没有使用过可编程编程语言。我为什么要开始呢?

And by the way, when do I get the speed and power you keep promising?

顺便问一下,我什么时候能得到你一直承诺的速度和力量?

In short—what’s in it for me, now?

简而言之---- 现在我有什么好处?

This is the funda­mental ques­tion that Lisp advo­cates have to answer for new users. But more often, it’s side­stepped. I’m not picking on Raymond or Graham or Seibel. They’re excel­lent writers. As program­mers, they’re way out of my league. As I learn more about Lisps, I return to these arti­cles and they make more sense.

这是 Lisp 提倡者必须为新用户回答的基本问题。但更多的时候,它被回避了。我没有找雷蒙德,格雷厄姆或者塞贝尔的茬。他们是优秀的作家。作为程序员,他们远远超出我的能力范围。随着我对 lisp 的了解越来越多,我重新回到这些文章,它们变得更有意义。

But these arti­cles are also emblem­atic of a general weak­ness of messaging about Lisp. I say that not as a ranking member of the Lisp commu­nity, but rather as someone who spent a lot of time seeking an answer to that funda­mental ques­tion. I never got it.

但是这些文章也反映了 Lisp 消息传递的一个普遍弱点。我这么说并不是因为我是 Lisp 社区的高级成员,而是因为我花了很多时间来寻找这个基本问题的答案。我从来没有得到过。

Seibel is passing the buck when he says that to under­stand the bene­fits of Lisp, “you’re going to have to learn some Lisp and see for your­self”. Sure, this method works—using Racket for a few months finally made the bene­fits of Lisp clear to me. But it also required an invest­ment of about 100–200 hours.  + For more on the perils of taxing reader patience, see why does typog­raphy matter in Prac­tical Typog­raphy.

Seibel 说,要理解 Lisp 的好处,“你必须学习一些 Lisp 语言,然后自己去看”,这是推卸责任。当然,这个方法是有效的ーー使用 Racket 几个月后,我终于明白了 Lisp 的好处。但这也需要大约100-200小时的投资。+

That’s asking too much. If Lisp languages are so great, then it should be possible to summa­rize their bene­fits in concise, prac­tical terms. It should be possible to demon­strate the power of Lisp in one hour, not 100. If Lisp advo­cates refuse to do this, then we shouldn’t be surprised when these languages remain stuck near the bottom of the charts.

这要求太高了。如果 Lisp 语言如此伟大,那么应该可以用简洁实用的术语来总结它们的好处。应该可以在一小时内演示 Lisp 的强大功能,而不是100小时。如果 Lisp 的拥护者拒绝这样做,那么当这些语言仍然停留在图表的底部时,我们不应该感到惊讶。

So really—what’s in it for me, now?那么,说真的,我现在能得到什么好处呢?

In a word, expres­sive­ness: the measure of how easy it is to put your ideas into code. For instance, an expres­sive language like Racket lets you write the “Hello world” program like this:

一言以蔽之,表达性: 衡量将想法转化为代码的容易程度。例如,一种表达性语言,比如 Racket,可以让你像下面这样编写“ Hello world”程序:

"Hello world" “ Hello world”

1
"Hello world"

copy to clipboard

Whereas a less expres­sive language—I won’t name names—requires this:

然而,一种表达能力较差的语言(我就不说名字了)需要这样做:

public class HelloWorld { 公共类别 HelloWorld {
    public static void main(String[] args) { Public static void main (String [] args){
        System.out.println("Hello world"); (“ Hello world”) ;
    }
}

1
2
3
4
5
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}

copy to clipboard

Conci­sion is valu­able, but expres­sive­ness also embodies other qual­i­ties: preci­sion, read­ability, flex­i­bility, poten­tial for gener­al­iza­tion.

简洁是有价值的,但是表达性还包含其他特性: 精确性、可读性、灵活性、泛化潜力。

Compared to other languages, Lisps are tremen­dously expres­sive. Like the over­pow­ered Japanese motor­cycle I once owned, they go where you want, very quickly, with a minimum of input. If you’ve ridden a motor­cycle, then you know what I mean. If you haven’t, good news—Lisps are cheaper and safer.

与其他语言相比,lisp 具有极强的表达能力。就像我曾经拥有的那辆功率过大的日本摩托车一样,它们可以去任何你想去的地方,非常快,只需要最少的输入。如果你骑过摩托车,你就知道我的意思了。如果你没有,那么好消息是: 口齿不清更便宜,也更安全。

Here’s my ranking of the language features that offered the most imme­diate value to me, when I was a programmer new to the Lisp world. For each, I’ve noted whether it’s a feature of Racket specif­i­cally, or Lisps gener­ally.

当我还是一个初次接触 Lisp 世界的程序员时,下面是我对提供给我最直接价值的语言特性的排名。对于每一个,我都注明了它是 Racket 的一个特性,还是 lisp 的一般特性。

  1. Every­thing is an expres­sion. [Lisps] Most program­ming languages are a combi­na­tion of two distinct ingre­di­ents: expres­sions (things that are eval­u­ated to produce a value) and state­ments (things that denote an action). For instance, in Python, x = 42 is a state­ment, and x + 42 is an expres­sion.

    一切都是一种表达。大多数编程语言都是两种不同成分的组合: 表达式(计算以产生值的东西)和语句(表示动作的东西)。例如,在 Python 中,x = 42是一个语句,而 x + 42是一个表达式。

    State­ments and expres­sions are distinct because while expres­sions can be natu­rally nested with each other, state­ments and expres­sions cannot. For instance, in Python, this is a valid expres­sion:

    语句和表达式是不同的,因为表达式可以自然地相互嵌套,而语句和表达式不能。例如,在 Python 中,这是一个有效的表达式:

    42 + 101

    1
    42 + 101
    

    copy to clipboard

    And so is this, substi­tuting another expres­sion for the right-hand value:

    这个也是,用另一个表达式代替右边的值:

    42 + (100 + 100)

    1
    42 + (100 + 100)
    

    copy to clipboard

    But this is not valid:

    但这种说法站不住脚:

    42 + if 1 < 0: 42 + 如1 < 0:
             100
         else: 其他:
             200

    1
    2
    3
    4
    42 + if 1 < 0:
             100
         else:
             200
    

    copy to clipboard

    Why? Because in Python, a stan­dard if condi­tional is a state­ment, and can only be used in certain posi­tions.

    为什么? 因为在 Python 中,一个标准 if 条件是一个语句,并且只能在特定的位置使用。

    By making every­thing an expres­sion, however, Lisps remove this limi­ta­tion. Since expres­sions are nestable, anything in the language can be combined with nearly anything else. For instance, because an if condi­tional is an expres­sion, you can use it in place of a value:

    然而,通过把所有东西都变成表达式,lisp 消除了这个限制。由于表达式是可定义的,所以语言中的任何东西都可以与几乎任何其他东西结合起来。例如,因为 if 条件是一个表达式,所以你可以用它来代替一个值:

    (+ 42 (if (< 1 0) 100 200))(+ 42(如(< 10)100200))

    1
    ([+](http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))) 42 ([if](http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))) ([<](http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3c))) 1 0) 100 200))
    

    copy to clipboard

    “But wait! Python has a ternary condi­tional expres­sion!” It doesn’t change the essen­tial point, but OK—you can indeed write this:

    “但是等等! Python 有一个三元条件表达式!”它没有改变基本点,但是 ok ーー你确实可以这样写:

    42 + (100 if 1 < 0 else 200)42 + (如1 < 0则为100)

    1
    42 + (100 if 1 < 0 else 200)
    

    copy to clipboard

    But now suppose we want to use a condi­tional in place of the oper­ator, not the right-hand value. In a Lisp, because every­thing is an expres­sion—including the oper­ator itself—this is easy:

    但是现在假设我们想用一个条件来代替操作符,而不是右边的值。在 Lisp 中,因为一切都是一个表达式(包括运算符本身) ,所以这很简单:

    ((if (< 1 0) + *) 42 100) ((如(< 10) + *)42100)

    1
    (([if](http://docs.racket-lang.org/reference/if.html#(form._((quote._~23~25kernel)._if))) ([<](http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._~3c))) 1 0) [+](http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))) [*](http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._*)))) 42 100)
    

    copy to clipboard

    But if you try the same thing in Python, it will raise a syntax error:

    但是如果你在 Python 中尝试同样的事情,它会引起一个语法错误:

    42 (+ if 1 < 0 else *) 10042(+ 如1 < 0 else *)100

    1
    42 (+ if 1 < 0 else *) 100
    

    copy to clipboard

    Why? Because Python oper­a­tors are not expres­sions.

    为什么? 因为 Python 操作符不是表达式。

    This is a synthetic example. The point is not that you’d neces­sarily want to do this, but that Lisps permit it. You don’t run into the syntactic guardrails that are lurking in other languages. As a programmer, this simpli­fies your work, because every­thing snaps together easily. It also expands your possi­bil­i­ties, because you can combine parts of the language in unusual ways if you feel like it.

    这是一个合成的例子。重点不是你一定想这么做,而是 lisp 允许这么做。您不会遇到其他语言中潜伏的语法障碍。作为一个程序员,这简化了你的工作,因为所有的东西都可以很容易地组合在一起。它也扩展了你的可能性,因为如果你喜欢的话,你可以用不同寻常的方式组合语言的各个部分。

    It’s similar to the basic idea behind Legos. Other building sets offer special­ized pieces that can only fit together certain ways. But by sharing uniform measure­ments, Lego bricks offer maximum possi­bil­i­ties for combi­na­tions. This ends up being more flex­ible & more fun.

    这和乐高背后的基本理念很相似。其他建筑设置提供专门的部件,只能以某种方式组合在一起。但是通过分享统一的测量值,乐高积木提供了最大的可能性组合。这样最终会变得更加灵活和有趣。

    So it is with an expres­sion-based language. If you find this idea exciting, congrat­u­la­tions—you might be a Lisp programmer. (If you find this idea weird and scary, this is a good moment to bail out.)

    基于表达式的语言也是如此。如果你觉得这个想法令人兴奋,那么恭喜你,你可能是一个 Lisp 程序员。(如果你觉得这个想法很奇怪、很可怕,现在是时候退出了。)

  2. Every expres­sion is either a single value or a list. [Lisps] Single values are things like numbers and strings and hash tables. (In Lisps, they’re some­times called atoms.) That part is no big deal.

    每个表达式要么是一个值,要么是一个列表。[ lisp ]单个值是像数字、字符串和散列表这样的东西。(在 lisp 中,它们有时被称为原子。)这部分没什么大不了的。

    The list part, however, is a big deal. In a language like Python, the list is one data type within the language. But in Lisps, the list is more like an orga­nizing prin­ciple for every­thing that happens.  + The name “Lisp” is an abbre­vi­a­tion for “list processing”. So yes, you can use the list as a data type. But a func­tion call is also a list. In fact, the source code for the func­tion is a list. Actu­ally, the rest of the program is too. Lists are every­where.  + The fancy CS term for this prop­erty is homoiconicity.

    然而,清单的一部分是一个大问题。在 Python 这样的语言中,列表是语言中的一种数据类型。但是在 lisp 中,列表更像是一个对所有发生的事情的组织原则。所以,是的,您可以使用列表作为数据类型。但函数调用也是一个列表。实际上,该函数的源代码是一个列表。实际上,这个项目的其他部分也是。清单无处不在。+

    The bene­fits of lists are similar to that of expres­sions. By bringing more of the language into a consis­tent form, more possi­bil­i­ties arise for how pieces can be combined and manip­u­lated.

    列表的好处类似于表达式。通过把更多的语言变成一致的形式,更多的可能性出现,如何组合和操作的片断。

    Seibel describes Lisp as a tool for getting “more done, faster”. Here, you can start to see why this is so. Lisp languages are immensely flex­ible and permis­sive in how their pieces can be connected. This means that the way you think about a program­ming problem can be quite close to the way you actu­ally program it. (This is also why Lisps have tradi­tion­ally excelled for proto­types and exploratory work.)

    Seibel 将 Lisp 描述为“完成更多、更快”的工具。在这里,你可以开始明白为什么会这样。Lisp 语言在如何连接它们的片段方面非常灵活和宽松。这意味着你思考一个编程问题的方式可以和你实际编程的方式非常接近。(这也是为什么 lisp 传统上在原型和探索性工作方面表现出色。)

    To be fair, getting the most out of a Lisp means learning to think more in the Lisp idiom of lists and expres­sions. For that reason, I agree with Seibel—trying it your­self is the best way to be convinced of the bene­fits. As you get a feel for lists and expres­sions, it does pay increasing divi­dends throughout the language. You see how tiny lines of code can produce epic amounts of work. You also start to appre­ciate that even in a well-designed language like Python, you’re spending a lot of time shaping your ideas to fit its limi­ta­tions, like shaving an invis­ible yak.

    公平地说,从 Lisp 中获得最大收益意味着学会更多地使用 Lisp 语言中的列表和表达式。出于这个原因,我同意塞贝尔的观点ーー亲自尝试是确信这种方法的好处的最好方法。当你对列表和表达式有了一定的了解之后,你就会发现它在整个语言中的作用越来越明显。你可以看到微小的代码行是如何产生大量的工作的。您还会开始意识到,即使是在 Python 这样设计良好的语言中,也需要花费大量时间来塑造自己的想法以适应其局限性,就像剃一头看不见的牦牛一样。

  3. Func­tional program­ming. [Lisps] Yes, I know that other languages offer func­tional-program­ming features, and that Lisps aren’t consid­ered pure func­tional languages. But many program­mers haven’t been exposed to this idiom, and thus tend to under­rate its bene­fits. I know I was in that cate­gory.

    函数式编程。是的,我知道其他语言提供函数式编程特性,而且 lisp 并不被认为是纯粹的函数式语言。但是许多程序员没有接触过这种习惯用法,因此倾向于低估它的好处。我知道我属于那一类。

    Func­tional program­ming doesn’t mean program­ming with func­tions. Every­body does that. Func­tional program­ming refers to a stricter style where func­tions receive certain data as input, process only that data, and return a result. In func­tional program­ming, func­tions avoid two habits common in other languages: muta­tion (= changing data in-place rather than returning a value) and relying on state (= extra context that’s not provided as input, for instance global vari­ables).

    函数式编程并不意味着用函数编程。每个人都这么做。函数式编程指的是一种更严格的风格,其中函数接收某些数据作为输入,只处理该数据,并返回结果。在函数式编程中,函数避免了其他语言中常见的两个习惯: 变异(= 就地更改数据而不返回值)和依赖状态(= 没有提供作为输入的额外上下文,例如全局变量)。

    “Wait—I love state and muta­tion. Why would you take them away?” Because they’re false friends. They contra­dict the essen­tial concept of a func­tion, which is to encap­su­late data and algo­rithms. When a func­tion relies on state or muta­tion, it’s oper­ating outside those bound­aries. There­fore, you either take on an increasing house­keeping burden to keep track of how func­tions affect each other, or watch your program sink into a swamp of myste­rious, compli­cated bugs.

    “等待——我热爱国家和突变。你为什么要把他们带走?”因为他们是假朋友。它们违背了函数的基本概念,即封装数据和算法。当一个函数依赖于状态或变异时,它就在这些边界之外运行。因此,您要么承担越来越大的家务负担,以跟踪函数如何相互影响,要么眼睁睁地看着自己的程序陷入神秘而复杂的错误沼泽。

    Program­ming in a func­tional style takes more effort at the outset. But it encour­ages you to struc­ture the program in a clean, compart­men­tal­ized way. This pays off imme­di­ately in programs that are easier to test and debug. It’s also more likely to lead to reusable compo­nents, since func­tions are truly inde­pen­dent.

    函数式编程从一开始就需要更多的努力。但是它鼓励你以一种干净的、划分好的方式组织程序。这在易于测试和调试的程序中立即得到了回报。这也更有可能导致可重用组件,因为函数是真正独立的。

    This bite-the-bullet aspect of func­tional program­ming is another reason why you can get “more done, faster” with a Lisp. The differ­ence between proto­type and produc­tion code often ends up being small, because you don’t take as many short­cuts at the start. The program grows and evolves more smoothly because it’s easy to change one part without causing ripple effects else­where.

    函数式编程的这种咬紧牙关的方面是使用 Lisp 可以“完成更多、更快”的另一个原因。原型代码和生产代码之间的差异往往最终变得很小,因为您在开始时不会走那么多捷径。该计划的发展和演变更加顺利,因为它很容易改变一个部分,而不会引起其他方面的连锁反应。

  4. Macros. [Racket] Some Rack­e­teers quibble with this term, prefer­ring syntax trans­formers, because a Racket macro can be more sophis­ti­cated than the usual Common Lisp macro.

    宏。一些诈骗犯对这个词有些吹毛求疵,他们更喜欢语法变换,因为 Racket 宏比通常的 Common Lisp 宏更复杂。

    A macro in Common Lisp is a func­tion that runs at compile time, accepting symbols as input and injecting them into a template to produce new code.

    Common Lisp 中的宏是一个在编译时运行的函数,接受符号作为输入,并将它们注入模板以生成新的代码。

    Macros in Racket, on the other hand, rely on the concept of hygiene. They can handle Common Lisp-style macros, but also more elab­o­rate syntax rearrange­ments.

    另一方面,Racket 中的宏依赖于卫生的概念。它们可以处理 Common lisp 风格的宏,也可以处理更复杂的语法重排。

    But forget that—what’s in it for you? As a programmer, you end up getting two bites at the apple every time you run a file: Racket runs the macros (which alter the source code), and then the source code itself.

    但是忘了这些吧,这对你有什么好处呢?作为一个程序员,每次运行一个文件,你最终都会得到两个结果: Racket 运行宏(它改变了源代码) ,然后是源代码本身。

    Unlike some­thing like the C preprocessor, which is basi­cally a sepa­rate mini-language, Racket macros are them­selves Racket func­tions that give you access to every­thing in Racket. Like lists and expres­sions, macros add another layer of expres­sive possi­bil­i­ties.

    不同于 c 语言的预处理器,它基本上是一个单独的迷你语言,Racket 宏本身就是 Racket 的功能,它可以让你访问 Racket 中的所有内容。与列表和表达式一样,宏也增加了另一层表达的可能性。

  5. Create new program­ming languages. [Racket] When I first read that Racket could be used to create new languages, I had two thoughts—are they serious? and would I really want to do that? The answers were yes and oh hell yes.

    创建新的编程语言。当我第一次读到 Racket 可以用来创造新的语言时,我有两个想法ーー它们是认真的吗?我真的想这么做吗?答案是肯定的,当然肯定。

    Between expres­sions, lists, and macros, Racket gives you a huge amount of semantic flex­i­bility. But on top of that, it also adds syntactic flex­i­bility, in that you can define a reader that converts surface syntax into stan­dard Racket S-expres­sions, and an expander that deter­mines the meaning of these S-expres­sions.  + Paul Graham’s program­ming language Arc, a dialect of Lisp, was built on top of Racket.

    Racket 在表达式、列表和宏之间提供了巨大的语义灵活性。但除此之外,它还增加了语法的灵活性,因为您可以定义一个读取器,将表面语法转换为标准 Racket s 表达式,还可以定义一个扩展器,用于确定这些 s 表达式的含义。+

    You can use this facility to make special­ized dialects of Racket. Or imple­ment earlier languages. Or create entirely new languages with their own rules. You can use any of these languages within Dr­Racket to code new projects. (These special languages are some­times called domain-specific languages, or DSLs.) Scribble is a DSL based on Racket; Pollen is a set of DSLs based on Scribble.

    你可以使用这个工具来制作 Racket 的特殊方言。或者实现早期的语言。或者根据自己的规则创建全新的语言。您可以使用 DrRacket 中的任何一种语言来编写新项目。(这些特殊语言有时被称为领域特定语言,或 dsl。)Scribble 是一个基于 Racket 的 DSL; Pollen 是一组基于 Scribble 的 DSL。

    If you’re like most program­mers, you’ve never had a tool for making a new language, so you’ve not consid­ered it a real­istic approach to a problem. And you won’t need it all the time. But when you do, it is awesome, in both the new and old senses of that word.

    如果你像大多数程序员一样,你从来没有一个工具来创建一个新的语言,所以你不认为它是一个解决问题的现实的方法。而且你也不会一直需要它。但是当你这样做的时候,无论是从新的还是从旧的意义上来说,这都是令人敬畏的。

    (The sequel to this piece—Why language-oriented program­ming? Why Racket?—is devoted to this topic.)

    (这篇文章的续篇《为什么是面向语言的程序设计? 为什么是敲诈? 》专门讨论了这个话题。)

  6. Libraries & docu­men­ta­tion. [Racket] This might not look like a compet­i­tive differ­en­tiator—doesn’t every program­ming language have libraries & docu­men­ta­tion?

    图书馆和文档。[ Racket ]这看起来不像是一个有竞争力的区分器ーー难道不是每种编程语言都有图书馆和文档吗?

    Yes, but prob­ably not like this. As a conse­quence of being used in research settings for many years—Racket’s core devel­op­ment team is made of computer-science profes­sors—Racket’s libraries & docs are more like a trans­mis­sion from a highly evolved alien intel­li­gence.

    是的,但可能不是这样的。Racket 的核心开发团队由计算机科学教授组成。 racket 的图书馆和博士更像是高度进化的外星智慧的传播。

    You get the essen­tials, of course: web server, JSON, XML, drawing, foreign-func­tion inter­face, and so on. Then you notice pack­ages you maybe didn’t expect: GUI appli­ca­tion frame­work, math plot­ting, package-distri­bu­tion system, unit tester. Beyond that, your face starts to melt a little bit: seman­tics engi­neering? Futures visu­al­izer?

    当然,您得到了基本的东西: web 服务器、 JSON、 XML、绘图、外部函数接口等等。然后您注意到了您可能没有预料到的包: GUI 应用程序框架、数学绘图、包分发系统、单元测试器。除此之外,你的脸开始融化一点点: 语义工程?期货可视化工具?

    I won’t pretend to know what all this shit does. A lot of it is over my head. But I like that. Each week I use Racket, I end up exploring a new part of the library, and learning some­thing new. As opposed to other languages that seem to kill brain cells on contact (= pretty much anything named *Script, I find).

    我不会假装知道这些该死的东西是干嘛的。很多事情超出了我的能力范围。但我喜欢这样。每个星期我使用 Racket,我最终探索图书馆的新部分,并学习一些新的东西。与其他语言不同的是,这些语言似乎一接触就会杀死脑细胞(我发现几乎所有叫 * Script 的语言)。

    This learning is only possible because of Racket’s truly outstanding docu­men­ta­tion. It’s vast, thor­ough, precise, and approach­able. See for your­self.  + If you don’t like the typog­raphy and layout of the docs, blame me.

    这种学习是可能的,因为 Racket 的文档真的很出色。它是广阔的,彻底的,精确的,平易近人的。你自己看吧。+

  7. Dr­Racket. [Racket] Yes, I know how to use a command line. But Racket includes a cross-plat­form graph­ical IDE called Dr­Racket that’s pretty great. Dr­Racket lets you edit, run, and debug Racket source files (or any other language based on Racket—see item #9 on this list.)

    DrRacket.是的,我知道如何使用命令行。但 Racket 包括一个跨平台的图形化 IDE,叫做 DrRacket,这非常棒。DrRacket 允许您编辑、运行和调试 Racket 源文件(或者基于 Racket 的任何其他语言ー参见列表中的第9项。)

    No, it doesn’t have the Ginsu-level search-and-replace facil­i­ties of some­thing like Sublime Text. But it does have helpful editing features opti­mized for Racket code (for instance, you can right-click on a symbol name and rename it throughout the file, or jump from a func­tion to its docu­men­ta­tion).

    不,它没有像 Sublime Text 那样的 ginsu 级别的搜索和替换功能。但是它确实有一些为 Racket 代码优化的有用的编辑特性(例如,你可以在文件中右键单击一个符号名并重命名它,或者从一个函数跳转到它的文档)。

    More­over, the command line within Dr­Racket doesn’t just show plain text—it can show stacked frac­tions, draw­ings, math plots, and other unex­pected guests. If your command line does all that, by all means keep using it.

    此外,DrRacket 中的命令行不仅仅显示纯文本,它还可以显示堆叠的分数、图形、数学图表和其他意想不到的客户。如果您的命令行完成了所有这些操作,那么请务必继续使用它。

  8. X-expres­sions. [Racket] This choice is some­what biased by my work with Racket, which mostly involves docu­ment processing and type­set­ting. But related topics arise in most web program­ming. An X-expres­sion is a special native data struc­ture that Lisps use to repre­sent HTML and other XML-ish data.

    X 表达式。(Racket)这个选择有些偏颇,因为我在 Racket 的工作主要涉及文件处理和排版。但是相关的话题出现在大多数网络节目中。X-expression 是一种特殊的本机数据结构,lisp 用它来表示 HTML 和其他 xml 数据。

    Well, not “special” in a Lispy sense—keeping with the usual policy, an X-expres­sion is just another list—but special in the sense that other program­ming languages don’t have it. Usually your choice is to repre­sent HTML either as a string or as a full XML tree. A string is wrong because it doesn’t capture the struc­ture of the HTML, as defined by its tags and attrib­utes. An XML tree shows this struc­ture, but conceals the sequen­tial nature of the data elements, and is unwieldy to work with.

    嗯,不是 Lispy 意义上的“特殊”——与通常的策略一致,x 表达式只是另一个列表——但特殊的意义在于其他编程语言没有它。通常您的选择是将 HTML 表示为字符串或完整的 XML 树。一个字符串是错误的,因为它没有捕获 HTML 的结构,这是由它的标记和属性定义的。XML 树显示了这种结构,但隐藏了数据元素的顺序特性,使用起来很麻烦。

    An X-expres­sion ends up being an ideal hybrid between a string and a tree. More­over, because it’s just another list-based expres­sion in the language, you have a lot of options for processing it. Trans­lating an X-expres­sion to or from a text repre­sen­ta­tion using angle brackets is trivial and fast. (Details.)

    X 表达式最终是字符串和树的理想混合体。此外,因为它只是语言中另一个基于列表的表达式,所以您有很多处理它的选项。使用尖括号将 x 表达式转换为文本表示形式或从文本表示形式转换为 x 表示形式非常简单且快速。(详情)

    Given the close kinship between XML-ish data struc­tures and Lisp languages, I have no expla­na­tion why, during the Internet era, they’ve not been paired more often. They’re like peanut butter and jelly.

    考虑到 xml 数据结构和 Lisp 语言之间的紧密联系,我无法解释为什么在互联网时代,它们没有更经常地配对。它们就像花生酱和果冻。

  9. Scribble. [Racket] Pollen wouldn’t have been possible without Scribble, so for me, this has been the stone-cold killer feature of Racket. But that won’t be true for everyone, so I’m moving it down the list.  + Scribble was orig­i­nally created to serve as Racket’s docu­men­ta­tion language (a job it does well).

    Scribble.如果没有 Scribble,花粉是不可能存在的,所以对我来说,这就是 Racket 冰冷的杀手特征。但这并不适用于所有人,所以我把它从名单上往下移。+

    Scribble is a dialect of Racket that inverts the ordi­nary rela­tion­ship of plain text and code: rather than embed­ding text strings within source, a Scribble docu­ment consists of code expres­sions embedded within plain text.

    Scribble 是 Racket 的一种方言,它颠倒了普通的纯文本和代码之间的关系: Scribble 文档不是在源代码中嵌入文本字符串,而是在纯文本中嵌入代码表达式。

    “So it’s like an HTML template language.” Yes, in the sense that a template language allows code to be embedded in text. But also no, because a template language is usually a pidgin version of a real program­ming language. Scribble, by contrast, lets you invoke any Racket code simply by adding a command char­acter to the front. In keeping with the theme already estab­lished, this approach is both simpler (because there’s almost nothing new to learn) and more powerful (because you can invoke anything in Racket).

    “所以它就像一种 HTML 模板语言。”是的,在某种意义上,模板语言允许代码嵌入到文本中。但也不是,因为模板语言通常是真正编程语言的洋泾浜版本。相比之下,Scribble 只需在前面添加一个命令字符,就可以调用 Racket 代码。为了与已经建立的主题保持一致,这种方法不仅更简单(因为几乎没有什么新东西需要学习) ,而且更强大(因为您可以调用 Racket 中的任何东西)。

    In its combi­na­tion of text and code, Scribble has more kinship with La­TeX. While it doesn’t have the type­set­ting facil­i­ties of La­TeX, the program­ming facil­i­ties are much better.

    在文本和代码的结合方面,Scribble 与 LaTeX 有更多的亲属关系。虽然它没有 LaTeX 的排版工具,但是编程工具要好得多。

**Oppor­tu­ni­ties to partic­i­pate.** [Racket] In theory, open-source soft­ware projects create the oppor­tu­nity for groups of devel­opers to join together and make better things in collab­o­ra­tion than they could sepa­rately.

参与的机会。[ Racket ]理论上,开源软件项目为开发者团队创造了机会,他们可以通过合作创造出比单独开发更好的东西。



In prac­tice, I’ve found that they sort into a bimodal distri­bu­tion: over here, the under­doc­u­mented solo projects that sputter along fitfully (if at all); over there, the mature, popular projects that can be intim­i­dating for new contrib­u­tors.

实际上,我发现他们就像一个双峰分布: 在这里,那些未被充分记录的单独项目断断续续地(如果有的话) ; 在那里,那些成熟的、受欢迎的项目可能会吓到新的贡献者。



As an open-source project, [Racket](https://github.com/racket/racket) is posi­tioned at a happy medium. The core devel­op­ment team has been working together for years, and the commits remain [fast & furious.](https://github.com/racket/racket/commits/master) But they’re friendly scien­tists, not Shire-dwelling egotists, and remain recep­tive to improve­ments across the whole system. If you have a better idea, they’ll listen; if you code it up to their stan­dards and make a pull request, they’ll take it.

作为一个开源项目,Racket 被定位为一个快乐的媒介。核心开发团队已经一起工作了多年,而且提交仍然非常快速和激烈。但是他们是友好的科学家,不是住在夏尔的自大者,并且仍然愿意接受整个系统的改进。如果你有更好的主意,他们会听; 如果你按照他们的标准编码,并提出拉请求,他们会接受。



_[2021 update: I [no longer contribute](why-i-no-longer-contribute-to-racket.html) to Racket due to abuse & bullying by the project lead­er­ship. Everyone in the broader Racket commu­nity, however, has always been helpful and kind.]_

[2021年更新: 由于项目领导的辱骂和欺凌,我不再为 Racket 做贡献。然而,Racket 社区的每一个人都一直是乐于助人和善良的

The point of this list has been to tell you about the posi­tives. That doesn’t mean there aren’t nega­tives. The small pool of Racket program­mers means that when you hit a pothole, it’s possible no one’s ever seen your problem (= the inverse of Linus’s Law). If I wanted to hire a Racket programmer, the options would be few.

这个列表的意义在于告诉你积极的一面。这并不意味着没有负面影响。这个由 Racket 程序员组成的小群体意味着,当你遇到坑洞时,可能没有人看到过你的问题(= 与 Linus 定律相反)。如果我想雇佣一个 Racket 的程序员,选择很少。

Still, why shouldn’t I be enthu­si­astic? What I’ve been able to accom­plish so far with Racket has been tremen­dously useful, educa­tional, and fun—the most fun I’ve had in 25+ years of program­ming.

不过,我为什么不能热情一点呢?到目前为止,我在 Racket 上取得的成就是非常有用的、有教育意义的和有趣的ーー这是我在25年以上的编程生涯中所获得的最大乐趣。

If you think I sound like a fanboy or cult member, I can live with that. But those are people whose enthu­siasm is dispro­por­tionate to reality. Here, I’ve tried to stay out of the clouds (and the weeds) and explain the concrete, prac­tical features that have made Racket such a plea­sure in my own work.

如果你觉得我听起来像个狂热粉丝或者邪教成员,我可以接受。但这些人的热情与现实不成比例。在这里,我试图远离云彩(和杂草) ,并解释具体的,实际的特点,使 Racket 在我自己的工作中如此愉快。

As always, your mileage may vary. But if I persuade a few people to down­load Racket and try it, I’ll be happy. In fact, if you try it and don’t like it, I invite you to contact me, because I’m always curious to hear dissenting opin­ions.

和往常一样,你的目标可能会有所不同。但是如果我能说服一些人下载 Racket 试试,我会很高兴的。事实上,如果你尝试过但不喜欢,我邀请你联系我,因为我总是很好奇听到不同的意见。

I will end by taking on the big kahuna—

最后,我将挑战大人物

Does “profound enlight­en­ment” await? 等待着“深刻的启蒙”吗?

I won’t claim I’ve reached the top of the moun­tain. But I can tell you what the view looks like so far.

我不会说我已经到达山顶。但是我可以告诉你到目前为止的情况。

There’s a sense in which Lisp and its descen­dants are more than program­ming languages. They’re tools in the broader intel­lec­tual inquiry into the theory of compu­ta­tion. Lisp’s inventor, John Mc­Carthy, orig­i­nally consid­ered Lisp a “way of describing computable func­tions much neater than the Turing machines”, adapting the nota­tion of lambda calculus to do so. Racket, like­wise, has grown out of scien­tific research and explo­ration.

从某种意义上说,Lisp 及其后代不仅仅是编程语言。它们是对美国计算理论进行更广泛的智力调查的工具。Lisp 的发明者 John McCarthy 最初认为 Lisp 是“描述可计算函数的一种比图灵机简洁得多的方法”,他采用了 lambda 微积分的符号来实现这一点。同样,球拍也是从科学研究和探索中发展起来的。

The theory of compu­ta­tion is just one of many great scien­tific discov­eries in the last 100 years. But I don’t get to use quantum mechanics or rela­tivity or DNA sequencing in my daily work. When I’m program­ming, however, I’m using compu­ta­tion.

计算理论只是过去100年里众多伟大科学发现中的一个。但是在我的日常工作中,我没有使用量子力学或相对论或 DNA 序列。然而,当我在编程时,我使用的是计算。

Racket, as a Lisp dialect, has many prac­tical bene­fits. But it also opens a window onto a vast theo­ret­ical world that under­lies every­thing we can do with programs. I’m not a brainiac computer scien­tist. But some days, through that window, I can start to see a bit of what they see—some math, some science, a lot of truth, and more than a little beauty and mystery.

Racket 作为一种 Lisp 方言,有许多实际的好处。但它也为我们打开了一扇通向广阔理论世界的窗口,这个理论世界是我们用程序所能做的一切事情的基础。我不是一个聪明的计算机科学家。但有时候,透过这扇窗户,我开始看到他们所看到的一些东西ーー一些数学、一些科学、许多真理,以及一点点美丽和神秘。

Paul Graham calls Lisp a “secret weapon”. I would clarify: Lisp itself isn’t the secret weapon. Rather, you are—because a Lisp language offers you the chance to discover your poten­tial as a programmer and a thinker, and thereby raise your expec­ta­tions for what you can accom­plish.

Paul Graham 称 Lisp 为“秘密武器”。我想澄清的是: Lisp 本身并不是秘密武器。而是因为 Lisp 语言让你有机会发现自己作为程序员和思考者的潜力,从而提高你对自己能够完成的事情的期望。

If that’s not a step toward enlight­en­ment, I don’t know what is.

如果这不是通向启蒙的一步,我不知道什么是。

分类:

后端

标签:

后端

作者介绍

逸之
V1