Greenspun的第十条规则,每个大型项目都包括Lisp解释器吗?[关闭]


12

Greenspun的第十条规则(实际上是唯一一条规则)指出:

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

我的记忆是,有一些关于该主题的论文,也许是针对Borland的Quattro(电子表格)项目的,可能还有其他论文。Google没有帮助,也许没有想到合适的搜索词。我正在寻找支持该主张的论文或文章。


8
您是否在Wikipedia文章上阅读了该规则含义解释?我怀疑是否会作出认真的努力来确认或反驳这一主张,但这并不是真的要认真对待
扬尼斯

3
有趣的是,尽管Greenspun的规则只是个玩笑,但实际上我确实在开发具有嵌入式LISP解释器的仿真软件。该软件的配置全部通过S-Expressions完成,并且可以想到可以编写LISP代码来完成配置中的各种操作。
wkl 2012年

@YannisRizos-从字面上看,您的任何链接都没有声称该规则是个玩笑。莫里斯定律就是这样构成的。现在,具有象征意义的....
Casualcoder

2
@casualcoder “具有讽刺意味的是,这在我去世后可能是任何人都记得我写的一件事。” 该规则的命名暗示该规则是以轻松的方式编写的……
yannis 2012年

关于Erlang和并发程序是否没有类似的报价?
乔治

Answers:


15

该说法夸张。但是,在其他语言中,有明显的Lisp嫉妒迹象。看一下C#及其在本质上如何变得越来越有用。看一下各种业务流程管理,工作流和EAI框架,这些框架使他们能够在不更改程序的情况下对系统进行编程。

马丁·福勒(Martin Fowler)有一本关于领域特定语言的书,谈到了如何使用面向对象的语言进行元编程。因此夸张有一些道理。

Paul Liham在Lisp附带的第一批名单中将Lisp称为最强大的语言,很容易看出为什么许多语言相比之下显得苍白。

绕过第十条规则的方法是多语言编程。意识到一种语言/框架不是金锤。然后,您可以只使用Lisp,而不是创建一个糟糕的,临时的Lisp实现。


4
权力和年龄是独立的。与创建LISP时的优劣确实无关紧要,与今天的语言相比,这很重要。第一次完全不重要。
DeadMG

2
@DeadMG,与尚未从Lisp移植到其他语言的东西相比,这些“第一”什么都没有。
SK-logic

1
@DeadMG,您是对的。人们开始研究Ruby之后,对它的钟爱之一就是它的元编程方面。Lisp具有内置功能。C#开发人员喜欢LINQ(有充分的理由),并且喜欢声明式编程对并发的影响。Lisp黑桃色的。随着系统变得越来越复杂,它们变得更多地是关于节点对消息作出反应,而不是关于对象。Lisp从这里开始,大多数其他语言都必须临时(因此遵守规则)或通过框架(例如Biztalk,Tibco等)来添加它。
迈克尔·布朗

2
“您可以只使用Lisp而不是创建Lisp的不良,临时实现,而莫里斯的推论意味着您仍在使用不良的,临时性实现;)
jk。

1
该条目的完美注解“整个骇客文化通常被骇客自己视为“只哈哈哈”(ha-ha-only-serious);过分轻视或太过认真地表示一个人是局外人,迷路者或处于幼虫阶段。 ”
迈克尔·布朗

10

格林斯潘的“第十条规则”是一条贪吃的蛇。当延伸得足够远时,如果使它涵盖“任何脚本或配置系统”,那么显然此问题的答案将是“是”,因为配置在某种程度上是任何不平凡的程序都需要的,而脚本随着复杂度的提高,这种情况很少见。

另一方面,请看看NALDY DOG为游戏编程发明的Lisp变体GOAL。它看起来根本不像“经典的” Lisp。这是一个高度命令式的系统,具有面向对象的功能,没有解释器,对垃圾回收的支持最少(而是依赖于运行时级别的清理工具),并且广泛支持内联汇编。

换句话说,当他们尝试使用Lisp进行足够复杂的项目时,他们发现要做任何有用的事情,他们都必须将语言转换为临时的,非正式指定的C ++一半的实现!;)(而且最终设计人员离开后,他们最终不得不停止使用它,因为没人能理解他的代码。)


我想我的问题是关于大型系统的特定部分。最终,由于使用该语言所涉及的思维过程或技术,而不是固有的速度或优越性,因此该系统将具有使用另一种语言编码的更好的部分。勒纳汉先生的故事就是一个例子。
Casualcoder 2012年

实际上,他们停止使用GOAL,因为他们被代码库为C ++的公司收购了。另外,GOAL相当虚弱。不要假设最低分母的在线教程和大学讲座是正确的:)
p_l 2012年

9

奇怪的是,Programmers SE中已经存在对此问题的一个答案。

引用相关部分:

Greenspun的观点是(部分)许多复杂的程序都内置了解释器。他建议与其使用一种已经内置了解释器(或编译器)的语言(例如Lisp),而不是将解释器构建为一种语言。

当时,我正在开发一个相当大的应用程序,该应用程序使用用于自定义语言的自定义解释器执行用户定义的计算。我决定尝试在Lisp中重新编写其核心,作为大规模实验。

花了大约六个星期。原始代码是约100,000行的Delphi(Pascal变体)。在Lisp中,减少到10,000行。然而,更令人惊讶的是,Lisp引擎的速度提高了3-6倍。请记住,这是Lisp新手的工作!整个经历让我大开眼界。我第一次看到了将一种语言的性能和表现力结合在一起的可能性。
- 迈克尔·莱纳汉Michael Lenaghan)

为了进一步阐明这一部分,Michael回应了以下评论:

哇,如果它能以比Lisp实现慢3-6倍的速度运行,那一定是一些非常可怕的Delphi代码!”正确,我认为这是我未能更好地解释它的失败。Lisp实现能够进行转换用户表达式转换为Lisp表达式(一个简单的过程),然后将Lisp表达式编译为本机代码(经过全面优化),这就是Greenspun的《第十条规则》的含义。
-Michael Lenaghan

鉴于此答案是由其他人的答案组成的,它是社区Wiki。


2

规则是个玩笑,但其中有些道理。任何复杂的系统都将包含许多已解释的部分(请参阅“解释器模式”在相信所有这些模式的人中都非常流行)。任何复杂的系统都必须提供一些配置方法,这些配置方法通常是结构化的,经常被解释的。

任何复杂的系统都很可能在其构建过程中具有多次代码生成过程和各种自定义的预处理器(请考虑诸如mocQt或tablegenLLVM中的情况)。

许多系统使用一组(几乎总是)设计不当的树遍历和转换工具来处理复杂的树状数据结构,这些工具非常类似于Common Lisp的库功能。

所有这些东西都是Lisp免费提供的,并且在大多数情况下,所有临时的,计划外的,没有经过足够充分实施的思想都将完全不如前者。


2

任何足够复杂的系统都会具有特定于领域的概念和要求,这些概念和要求很难用您所使用的语言的抽象来表达。这无意间迫使程序员创建了特定于领域的抽象,以减轻弥合编程语言之间的语义鸿沟的负担。以及特定的域。一旦有了足够的这些抽象,您就基本上可以拥有一种针对特定领域的语言的解释器。这是软件开发中不可避免的部分。


1

该规则可能会更准确(并且不太有趣),因为“将需要基于大型软件的系统来实现动态行为”。

这可以通过两种方式完成:

  1. 具有数十个参数和数百个定义的大型复杂配置文件。

  2. AD-HOC脚本语言。

“ sendmail”可能是类型“ 1”的典型示例。我想不出任何类型“ 2”的好例子,这些例子不涉及在Warcraft / LUA甚至Netscape / Javascript中嵌入“真实”脚本语言。

问题在于几个参数可以通过配置文件快速简便地实现,但是这种解决方案并不能真正扩展。但是,在向配置文件添加一个或两个选项时,转而使用脚本方法转储配置文件绝对不经济。因此,解释配置文件的代码最终只是一个写得不好的解释器。


0

正如其他人所述,这可能是事实,许多程序需要可配置性,因此确实包含各种类似Lisp的解释器。

但是,该语句还带有笑意,这意味着编写程序所需的全部是Lisp,并且所有其他语言都不如它。

但这是错误的,Lisp可能具有表达能力,但它也太抽象了,它试图隐藏平台的细节,并且假装计算机世界中只存在列表。

高性能编程的现实是,有时候我们确实需要混和一些比特和字节,并做特定于OS的工作,因此不可能只使用Lisp来完成所有声明。

恰恰相反,无论您发明的语言多么复杂,聪明或复杂,最终它都是编写汇编的另一种方式。


似乎只与50年代后期最古老的Lisp环境有关。我个人发现Common Lisp的处理位的功能可能是最好的功能之一(主要竞争对手是Erlang)。数组,哈希表,结构都是常见的。
2012年

为Lisp编写编译器很容易,因为您不需要解析它。可以制作Lisp函数,并使用宏编译器(就像Lisp评估器一开始只是一页到一半的代码)将这些List表达式转换为C,并且您正在用Lisp用C编写代码,但具有全部功能宏和lambda演算(如果需要)。
aoeu256 '19

0

无论是否要认真对待它,我从事的最大的C和C ++项目都是如此。

自定义脚本语言类似于Common Lisp,这是不对的。正面的示例类似于Scheme(因为更聪明的设计师将Guile,SpiderMonkey和Lua集成在一起,而不是发明自己的语言。)最值得DailyWTF借鉴的示例是Forth类语言和MUMPS类语言。

另一个示例(不确定它是否可以算作Greenspunning,但肯定是WTF)是用于通用脚本的XSLT解释器。这更像Lisp,因为他们添加了一个反馈循环,在该循环中,输出将再次进行XSLT转换-因此,现在您实际上有了宏。
不过,这样做的动机不是要获得lispy功能,而是要避开公司的代码QA程序(这给每个错误修复增加了3周的等待时间。XML被视为“数据”,并且不受此过程的限制。)


-1

不幸的是没有!

最好只是嵌入一个真正的Lisp(y)解释器(javascript或lua alos可以很好地完成工作),但在项目中添加自制4gl可以减小总体大小,同时增加灵活性。

“对所有内容进行编码”的项目具有更大的模块数量,并且变得笨拙且僵化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.