【问题标题】:Is ECMAScript really a dialect of Lisp?ECMAScript 真的是 Lisp 的方言吗?
【发布时间】:2011-02-17 14:33:58
【问题描述】:

我的一个朋友4th European Lisp Symposium的欢迎信息引起了我的注意:

... 的实现和应用 任何 Lisp 方言,包括 Common Lisp、Scheme、Emacs Lisp、 AutoLisp,ISLISP,迪伦,Clojure, ACL2、ECMAScript、...

然后问ECMAScript是否真的是Lisp的方言。真的可以这么认为吗?为什么?

是否有一套定义明确且明确的标准来帮助我们检测一种语言是否是 Lisp 的方言?或者是一种非常松散的方言(在这种情况下,我们可以将 Python、Perl、Haskell 等添加到 Lisp 方言列表中吗?)

【问题讨论】:

  • 我听说它被称为“C 语言中的 Lisp”,这是有道理的。
  • 请参阅 this SO question,了解 Haskell 上下文中的相同讨论。
  • 你在质疑 ECMAscript 而不是 Dylan? :-)
  • @Ken:Dylan一直被宣布为 Lisp 方言;如果不是这样,Lispers 家现在不会注意到吗? (我的理解是,s 表达式总是被设计得相当抽象,而更具体的语法已经计划“现在很快”很长一段时间了......)
  • JavaScript 具有可变状态,但在函数式编程中,特别是 Lisps,一个 avoids that kind of hard-to-think-about hackery 历史上来自图灵机的意象,并在编程时尝试接近机器,因为限制机器功率。这是至关重要的。所以没有。

标签: javascript lisp ecma262


【解决方案1】:

Brendan Eich 想为 Netscape 开发一种类似于 Scheme 的语言,但现实介入了,他最终不得不使用一些 看起来 模糊地像“普通”人的 C 和 Java 的东西,但是这工作就像一种函数式语言。

我个人认为将 ECMAScript 称为“Lisp”是不必要的,但对每个人来说都是他自己的。真正的 Lisp 的关键似乎是数据结构表示法和代码表示法相同的特征,而对于 ECMAScript(或 Ruby 或 Python 或任何其他 Lisp 的动态函数式语言)则不然.

警告:我没有 Lisp 凭据 :-)

【讨论】:

  • +1 完全同意。如果我们要将带有函数式编程风格的语言视为 LISP 方言,则必须包括 C# 和 VB.NET。我真的不认为这两个算作 LISP 方言。我认为“代码即数据”是 LISP 的定义特征:如果有人试图命名具有“代码即数据”灵活性的非 LISP,就会明白为什么。
  • 它可能是 Lisp 中最知名的,也可能是 Lisp 中的第一名,但绝对不是 Lisp 独有的:en.wikipedia.org/wiki/Homoiconicity
  • @Ken 是的,谢谢,我今天正在查看其中的一些内容。奇怪的是,我读到一篇声称 SNOBOL 是同音异义的论文,考虑到我对它的模糊记忆,这让我有点惊讶:-)
  • @Sprague 是的,对不起;我可能不应该使用术语“JSON”。可能是动态类型和一流函数的结合让人们想到了 Lisp。
  • @R.MartinhoFernandes 一种具有“代码即数据”灵活性的非 Lisp 语言是 Forth 语言。那么为什么没有 Lisp 的连接语言如此强大呢?因为它们融合了一些相同的简单性——它们是可扩展的。几乎没有保留字,几乎没有语法,具有同音性,并显示出强大的功能模式,允许轻松组合(函数流水线),仅举几例。而其他连接语言,如 Factor、Joy 和 Cat,似乎也有类似的属性。这就像水晶和普通岩石之间的区别——纯度很重要!
【解决方案2】:

不是。正如您所指出的,它有很多功能根源,但现在许多其他非 lisp 语言也是如此。

Lisp 有一个使它们成为 lisp 的剩余特征,那就是 lisp 代码是根据 lisp 数据结构(同音性)编写的。这就是使 lisps 强大的宏系统成为可能的原因,也是为什么它在非 lispers 看来如此奇怪的原因。函数调用只是一个列表,其中列表中的第一个元素是函数的名称。

由于 lisp 代码只是 lisp 数据,因此可以使用元编程来做一些非常强大的东西,而这是其他语言无法做到的。许多 lisp,甚至像 clojure 这样的现代 lisp,在很大程度上都是作为一组宏实现的。

【讨论】:

  • 这比此页面上的任何其他内容都正确得多。
【解决方案3】:

尽管我不会将 JavaScript 称为 Lisp,但在我看来,它比大多数主流语言(甚至是函数式语言)更类似于 Lisp 的做事方式。

首先,就像 Lisp 一样,它本质上是一种基于无类型 lambda 演算的简单命令式语言,适合由 REPL 驱动。

其次,在 JavaScript 中嵌入文字数据(包括 lambda 表达式形式的代码)很容易,因为它的一个子集等同于 JSON。这是一种常见的 Lisp 模式。

第三,它的值和类型模型是非常 lispy。它在广义上是面向对象的,因为所有值都有一个标识的概念,但在大多数狭义上它并不是特别面向对象的。就像在 Lisp 中一样,对象是有类型的并且非常动态。代码通常被分成函数单元,而不是类。

事实上,在 JavaScript 世界中有几个(或多或少)最近的发展,让这门语言有时让人觉得很笨拙。以 jQuery 为例。在我看来,将 CSS 选择器作为子语言嵌入是一种非常类似于 Lisp 的方法。或者考虑一下 ECMAScript Harmony 的元对象协议:它看起来确实像 Common Lisp 的直接端口(比 Python 或 Ruby 的元对象系统要多得多!)。名单还在继续。

JavaScript 确实缺少宏和带有编辑器集成的 REPL 的合理实现,这是不幸的。当然,来自其他语言的影响也非常明显(不一定是坏的方式)。尽管如此,Lisp 和 JavaScript 阵营之间仍有大量的文化兼容性。有些可能是巧合(比如最近兴起的 JavaScript JIT 编译),有些是系统性的,但肯定存在。

【讨论】:

  • 这些是一般的无类型 lambda 演算方面,不是 Lisp 特有的。
  • 嗯...确实,方面#1 和#3 可能有些重叠。其他(命令性(!),子语言和文字数据的嵌入,MOP,JIT 编译)是否也遵循无类型的 lambda 演算核心?我会说他们没有,但话又说回来,这并不是作为逐个特征的比较,而是一种支持文化接近的论点。实际上,我不排除这种接近的全部原因可能是因为两者都比大多数语言更强烈地基于(对无类型 lambda 演算的命令式解释)。
【解决方案4】:

如果你调用 ECMAScript Lisp,你基本上是在断言任何动态语言都是 Lisp。由于我们已经有了“动态语言”,因此您将“Lisp”简化为无用的同义词,而不是让它具有更具体的含义。

Lisp 应该正确地引用具有某些属性的语言。

如果满足以下条件,语言就是 Lisp:

  • 它的源代码是树状结构的数据,它有一个简单的打印符号作为嵌套列表。每个可能的树结构都有相应的符号表示,并且容易被赋予作为构造的含义;符号本身不必扩展来扩展语言。

  • 树状结构数据是语言本身的主要数据结构,这使得程序容易被程序操作。

  • 语言具有符号数据类型。符号具有interned的打印表示:当符号的相同打印符号的两个或多个实例出现在符号中时,它们都表示相同的对象。

    • 符号对象的主要优点是它不同于所有其他符号。在 Lisp 程序的语义中,符号以各种方式与各种其他实体配对,从而充当这些实体的名称。
    • 例如,Lisp 的方言通常有变量,就像其他语言一样。在 Lisp 中,变量由符号(内存中的对象)而不是文本名称表示。当 Lisp 程序的一部分定义了某个变量 a 时,a 的语法是一个符号对象,而不是字符串 "a",这只是用于打印目的的符号名称。对变量的引用,即程序中其他地方写成a 的表达式,也是一个on 对象。由于符号的工作方式,它是同一个对象;然后,此对象相同性将引用连接到定义。对象相同性可以在机器级别实现为指针相等。我们知道两个符号值是相同的,因为它们是指向堆中相同内存位置的指针(符号类型的对象)。
    • 恰当的例子:具有a non-traditional memory management for most data types, including nested lists 的NewLisp 方言通过使符号以上述方式运行来对符号进行例外处理。没有这个,就不会是 Lisp。引用:“newLISP 中的对象(不包括符号和上下文)通过值复制传递给其他用户定义的函数。因此,每个 newLISP 对象只需要一个引用。” [强调我的]。传递符号(如通过值复制)也会破坏它们的标识:接收符号的函数不会得到原始符号,因此无法正确接收其标识。
  • Lisp 语言中的复合表达式(不是像数字或字符串这样的简单基元)由一个简单列表组成,其第一个元素是指示操作的符号。其余元素(如果有)是参数表达式。 Lisp 方言应用某种评估策略来将表达式简化为一个值,并引发它可能具有的任何副作用。
  • 我会暂时争辩说,由包含值对的二进制单元组成的列表,由一个特殊的空列表对象终止,可能应该被视为 Lisp 定义的一部分:整个业务能够通过在前面“consing”一个新项目来从现有列表中创建一个新列表,以及对列表的“first”和“rest”的简单递归等等。

然后我就停在那里。有些人认为 Lisp 系统必须是交互式的:提供一个带有监听器的环境,其中一切都是可变的,并且可以随时重新定义等等。有些人认为 Lisps 必须具有一流的功能:必须有一个 lambda 运算符等等。坚定的传统主义者甚至可能坚持认为必须有 carcdr 函数,支持不正确列表的点对符号,并且列表必须由单元组成,并以符号 nil 结束,表示空列表,也是一个布尔假。坚持carcdr 允许Scheme 成为Lisp,但nil 是列表终止符和错误规则

不过,我们越是深入了解“Lisp 方言”的定义,它就越会变得政治化;人们对他们最喜欢的方言(也许是他们自己创造的)因某些技术性而被排除在外而感到不安。坚持carcdr 允许Scheme 成为一个Lisp,但nil 是列表终止符并且错误排除了它。什么,Scheme 不是 Lisp?

因此,基于以上所述,ECMAScript 不是 Lisp 的方言。但是,ECMAScript 实现包含可以公开为 Lisp 方言和numerous such dialects have been developed 的功能。出于某些情感原因需要将 ECMAScript 视为 Lisp 的人也许应该对此感到满意:支持 Lisp 的语义已经存在,并且只需要一个合适的接口到该语义,可以在 ECMAScript 中开发并且可以互操作使用 ECMAScript 代码。

【讨论】:

  • 我赞成这个答案的完整性和彻底性,但我强烈建议您更正和改写某些部分,特别是在 carcdr 讨论以及第二个项目符号条目周围关于符号(第 5 个绝对项目符号,关于变量及其名称;很难理解)。
【解决方案5】:

不,不是。

为了被认为是一个 Lisp,一个必须是同音的,而 ECMAscript 不是。

【讨论】:

    【解决方案6】:

    不是“方言”。我在 70 年代学习 LISP 并且从那以后就没有使用它,但是当我最近学习 JavaScript 时,我发现自己认为它类似于 LISP。我认为这是由于两个因素:(1)JSON 是一个类似列表的关联结构,(2)看起来 JS 的“对象”本质上是 JSON。因此,即使您不像在列表中编写 LISP 那样使用 JSON 编写 JS 程序,但您几乎可以这样做。

    所以我的回答是,熟悉 LISP 的程序员在使用 JavaScript 时会有足够多的相似之处。 JS = LISP in a Java suit 之类的语句只是表达了这种感觉。我相信这就是它的全部。

    【讨论】:

      【解决方案7】:

      是的,是的。引用 Crockford 的话:

      “JavaScript 与 Scheme 有很多共同之处。它是一种动态语言。它具有灵活的数据类型(数组),可以轻松模拟 s 表达式。最重要的是,函数是 lambdas。

      由于这种高度相似性,[递归编程入门] 'The Little Schemer' 中的所有函数都可以用 JavaScript 编写。"
      http://www.crockford.com/javascript/little.html

      关于同音字,我建议用 JavaScript 搜索这个词。说它“不是同音”是真的,但不是故事的结局。

      【讨论】:

        【解决方案8】:

        我认为 ECMAScript 是 LISP 的一种方言,就像英语是法语的一种方言一样。有一些共同点,但你会在一个只知道另一个的情况下完成任务:)

        我觉得有趣的是,第四届欧洲 Lisp 研讨会的三个主题演讲中只有一个直接涉及 Lisp(另外两个是关于 x86/JVM/Python 和 Scala)。

        【讨论】:

        • 英语更像是德语的方言,但我跑题了。
        【解决方案9】:

        “方言”肯定是太过分了。尽管如此,作为一个学习并使用过 Python、Javascript 和 Scheme 的人,Javascript 显然比 Python 更具有 Lisp 风格(Coffeescript 可能更是如此)。

        至于欧洲 Lisp 研讨会为什么要将 Javascript 描述为 Lisp,显然他们想借助 Javascript 的流行度,因为 Javascript 的程序员人数比其他所有 Lisp 方言大很多倍。他们的名单合并了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-05
          • 1970-01-01
          • 2010-11-03
          • 1970-01-01
          • 2010-12-07
          • 2013-11-09
          • 1970-01-01
          相关资源
          最近更新 更多