保罗·格雷厄姆(Paul Graham):敏捷=力量

今天,我们在HackerNews上讨论了 Paul Graham 文章,并于2002年决定从不存在的角度恢复其翻译。

图片



通过代数符号压缩到狭小的空间中的意思是另一种情况,它有助于
我们习惯于借助它们进行推理。”
-Charles Babbage(1791-1871)


LL1邮件列表上有关LL1 Revenge的文章的讨论中,Paul Prescod提出了一个要点。

Python的目标是规则性和可读性,而不是简洁性。

乍一看,编程语言可能不应该声称是。据我了解,简洁(简洁,简洁,紧凑)=强度。如果是这样,然后进行替换,我们得到:

Python的目标是规则性和可读性,但不是功能。

反过来,这并不是一个很好的折衷方案(如果确实是一个折衷方案),这值得做出。好像您说的那样:Python语言的目标不是成为一种有效的编程语言。

简洁=力量?对于那些参与语言开发的人来说,这似乎是一个重要的问题,也许是最重要的问题。我尚不确定答案是否是“是”,但首先,这是一个很好的假设。

假设


我的假设是,简洁就是力量,或者它们是如此之近,以至于除病理性病例外,您都可以将它们用于相同的事物。

在我看来,简洁是为编程语言创建的。如果计算机直接获得了机器语言的指令,计算机也会同样高兴。我认为我们要开发高级语言的主要原因是要获得在高级语言中表达(更重要的是思考)十行的优势,这将需要1000行机器代码。换句话说,高级语言的主要目标是使源代码更短。

如果较短的源代码是高级语言的目的,并且某种东西的强度可以衡量达到目标的程度,那么编程语言的强度就是可以减少您的程序。

相反,不能使程序变小的语言对编程语言的作用不佳,就像裁切不佳的刀或打印不清晰一样。

指标


从什么意义上讲,这是更少的?源代码大小的最常见度量是行数。但是,这种度量标准之所以普遍,仅是因为它具有度量简便性,而且我认为没有人认为这是对程序大小的良好测试。语言在同一行上有不同的约定; C中相当多的行可能只有一两个分隔符。

另一个简单的测试是程序中的字符数,但这不是很好。某些语言(如Perl)的标识符要短于其他语言。

我认为,衡量程序大小的最佳方法是元素数量,其中元素可以成为源代码树中单独的顶点。变量或函数的名称是元素。整数或实数是元素;文本文字段是一个元素;模式或格式指令的元素是一个元素。有一些临界情况(“ -5”是一个元素还是两个?),但是我认为大多数情况在所有语言中都是相同的,因此它们不会对比较产生太大影响。

这种措施应该具体化,在某些特定语言的情况下可能需要额外的解释,但是在我看来,它正在尝试衡量正确的事情:程序的部分数量。源代码树是您想到的用来表示程序的树,因此该树的大小与编写或读取它所需的工作量成正比。

设计


这项措施将使我们能够比较不同的语言,但至少对我而言,这不是其基本价值。简短测试的价值是设计语言的指南。最有用的语言比较是比较同一语言的两种可能的变体。我可以用哪种语言使程序更简短?

如果程序的概念负荷与它的复杂度成正比,并且给定的程序员可以承受一定的概念负荷,那么这就像在问:如何帮助程序员做更多的事情?在我看来,这就像在问:如何设计一种好的语言?

(顺便说一句,在设计语言时最明显地看出了这种已经很胡须的虚假说法:``所有语言都是等效的。当您创建一种新语言时,您会不断地比较两种语言-一种我会制作X,另一种我不会制作-所以决定最好的方法。如果这是没有意义的问题,您也可以投掷硬币。)

简洁的目标似乎是寻找新想法的好方法。如果您找到一种使程序更短的方法,那么这并非巧合:您可能会发现一个有用的新抽象。您甚至可以编写一个程序来获取源代码中的重复块。在以简洁而著称的语言中可以找到新的想法:Forth,Joy,Icon。

比较方式


据我所知,第一个写这些东西的人是弗雷德·布鲁克斯(Fred Brooks)和他的《神话人月》(Mythical Man-Month)。他写道,不管语言如何,程序员都会生成相同数量的代码。当我20多岁时第一次读它时,这真是一个很大的惊喜,在我看来,这产生了巨大的后果。这意味着(a)编写程序更快的唯一方法是使用较短的语言,(b)讨厌这样做的人会问那些不这样做的竞争者。

布鲁克斯的猜想,如果属实,可能是黑客入侵的本质。从那以后,多年来,我一直关注与该问题相关的所有事情:从理论研究到有关单个项目的故事。我没有发现任何与这一假设相矛盾的东西。

但是我没有看到任何明确的证据,并且我不希望看到它们。诸如比较Lutz Prekelt编程语言之类的研究虽然可以产生预期的结果,但它们倾向于使用对于有意义的测试而言太小的任务。对语言的最佳测试是一个月编写的程序会发生什么。而且,如果您像我一样确信语言的主要目的是要成为他们思考的一种良好的语言(而不是在您考虑之后便向计算机提供指令的语言),那么对该语言的真正考验是您可以在上面写些什么。因此,比较基于预定义规范的语言有些错误。

语言的真正考验是您如何找到并解决语言上的新问题,而不是别人制定的任务。这些是不同的标准。在艺术中​​,如果您事先知道想要得到什么,那么诸如刺绣和镶嵌之类的工具就可以很好地工作,但是如果您不知道,那绝对是不雅的。如果要在写图片的过程中显示图像(在显示诸如人的图像之类的复杂事物时应执行的操作),则应使用更灵活的工具,例如铅笔,墨水或油漆。当然,挂毯和马赛克是这样制作的:首先创建图片,然后才将其复制。

这意味着我们不太可能正确比较编程语言的相对强度。我们将进行精确的比较,但没有正确的比较。特别是,明确针对语言比较的研究可能会使用少量任务,并且必然会使用一组预定义的任务,因此往往会低估最强大的语言。

尽管该领域的报告不如“科学”研究准确,但可能更有意义。例如,来自爱立信的Ulf Wieger进行了一项研究,得出的结论是,Erlang比C ++短4-10倍,并且其上的软件开发速度也相应地更高:

爱立信内部项目的比较表明,无论使用哪种语言(Erlang,PLEX,C,C ++或Java),每小时代码行(包括开发的所有阶段)的生产率都差不多。语言上的差异-仅源代码总数上的差异。


这项研究还清楚地表明它并未出现在Brooks的书中(因为它只测量了调试代码的行):用更强大的语言编写的程序倾向于包含更少的错误。这已经足够了,并且可能在诸如网络交换机之类的任务中,这比程序员的性能更重要。

口味


最后,您可以相信自己的直觉。用这种语言编程是什么?我认为,为了创建更好的语言,您应该对语言在其中的思考能力变得敏感,然后选择或开发一种最适合您的语言。如果该语言的任何不便或限制之处-不用担心,您会知道的。

但是这种过敏会导致笨拙的语言对您来说变得难以忍受。我发现用没有宏的语言进行编程的限制难以忍受,就像习惯于动态类型的人会认为对语言的返回具有难以忍受的限制一样,应该为每个声明的变量描述类型,并且不可能声明由元素组成的列表不同种类。

我并不孤单。我知道许多Lisp黑客都曾发生过类似的事情。实际上,最准确的度量语言相对强度的方法可能是知道给定语言的程序员所占的比例,无论从事哪个学科领域,从事该语言的任何工作。

局限性


也许许多黑客都知道这种语言似乎有限制时的感觉。这可能与您要在大街上堵车并要绕行而造成的感觉相同。您想说些什么,而语言不允许您这样做。

实际上,限制语言不是简洁的语言。问题不在于您无法表达某些东西,而是该语言迫使您进行的绕道太长。做这个思想实验:您想编写某种程序,而该语言不允许您按照计划的方式进行操作,而是使它变得更短。至少对我而言,这并不是太严格。好像警察会引导您从交通堵塞中驶向一条较短的道路,而不是漫长的绕道。哇!

在我看来,局限性的感觉基本上是(降低了90%?)源于这样一个事实,即与您所考虑的语言相比,您不得不用自己编写的语言来使程序更长的时间。有界性基本上不够简洁,因此当一种语言似乎受到限制时,这意味着它不够简短。

可读性


我开始引用的内容还提到了另外两个特性:规律性和可读性。我不太了解什么是规则性,与仅可读性代码相比,常规性和可读性代码有什么好处?但是我想我知道可读性的含义,在我看来,这也与简洁有关。

在这里,我们必须谨慎对待单行代码的可读性和整个程序的可读性。只有最后一个很重要。我同意BASIC上的一行比Lisp上的一行更具可读性,但是用BASIC编写的程序将比用Lisp编写的同一程序具有更多行。阅读BASIC程序将花费更多的精力。

总工作量=阅读一行的工作量*行数


我不太确定可读性是否与简短程度成正比,但绝对简短是可读性的一个因素(请参见上面的公式)。因此,很难说这种语言的目的是可读性,而不是简洁性。

对于首次使用给定语言的用户,逐行可读性意味着该语言对他来说似乎是无害的。因此,逐行可读性可能是一个好的营销决策,尽管这是一个糟糕的设计决策。就分期付款方式而言,它是同构的:您不必为购买者每月支付一笔小额付款,而不必被一笔大笔的押金吓到。最终,对于他来说,部分付款对他无利可图,对于程序员而言,逐行可读性也无济于事。买方必须支付许多小笔款项,就像程序员必须分别阅读许多可读的行一样。

这个比率甚至在编程语言出现之前就已经存在。如果您阅读小说和报纸文章,那么您第一次阅读数学文章的经历可能会令人恐惧:阅读一页纸需要半个小时。尽管如此,我确信问题并不出在符号上,乍一看似乎没有。数学文章很难读,因为这些思想本身很复杂。如果您在散文中表达相同的想法(就像数学家在想到一个简短的符号之前所做的那样),那么阅读它们就不会容易,因为这一页会变成一整本书。

在什么程度上?


有些人不同意简洁=力量。我认为,与其争论是否如此,不如问一下权力的简洁程度会更有用吗?因为很明显,简洁性是编程语言的主要目的之一。如果不是,那么它们的目的是什么,其他功能又有多重要?

我建议这样做不是为了使讨论更加文明。我真的很想知道答案。语言什么时候足够简洁?

我开始的假设是,除某些病理情况外,简洁与力量相同。我的意思是,它们在某人开发的任何语言中都将是相同的,但是如果某人想要创建一种专门用于反驳此假设的语言,那么它可能会奏效。但是我也不是很确定。

语言但不是程序


应该明确的是,我们谈论的是语言的简洁性,而不是单个程序。当然,某些程序可以非常紧密地编写。

我在《关于Lisp》一书中写道。为了使宏证明其自身合理性,必须相对于其自身长度节省很多倍的空间。如果某个庞大的宏每次使用都会节省十行代码,而宏本身由十行组成,那么使用两次以上将节省行数。但这仍然是一个不好的举动,因为宏定义比常规代码更难以阅读。在提高可读性之前,您可能需要使用10次或20次宏。

我敢肯定,在任何语言中,这种妥协都是可能的(尽管我怀疑使用强语言会增加赌注)。每个程序员都曾经看到过由于可疑的编程技术而使代码大大缩短的情况。

因此,至少对于我来说,毫无疑问,程序可以足够简洁。问题是,语言本身会简短吗?语言可以强迫程序员以易读性为代价来简短地(按元素)编写吗?

很难想象一种过于简洁的语言的原因之一是,如果表达某种东西的方式过于紧凑,那么可能会有更长的方式。例如,如果您觉得在Lisp中使用宏或高级函数过于密集,则可以编写与Pascal同构的代码。如果您不想将Arc语言的阶乘表达为对高级函数的调用,

(rec zero 1 * 1-)

那么您还可以编写一个递归定义:

(rfn fact (x) (if (zero x) 1 (* x (fact (1- x)))))

尽管我不能立即给出示例,但我对这个问题感兴趣:该语言是否太短?是否有任何语言迫使您编写难以辨认的代码?如果有人有任何示例,我将很高兴看到它们。

(请记住:根据上述“元素”的度量,我对密度较高的程序感兴趣,但对短的程序不感兴趣,因为它们可以省略分隔符,并且所有名称的长度都为一个字符。)

它首先在此处发布




图片
通过参加SkillFactory在线课程,了解如何从头开始获得热门职业或技能和薪资水平提高的详细信息:




All Articles