【问题标题】:In Lisp/Racket/Scheme how is it possible to have an argument named `list`?在 Lisp/Racket/Scheme 中,怎么可能有一个名为 `list` 的参数?
【发布时间】:2020-09-14 05:59:20
【问题描述】:

list 不是在 Lisp 中创建新列表的 关键字,但在 Lisp 中可以有一个名为 list 的参数。我认为大多数编程语言(如 Java 或 C++)中的关键字不能用于 argument names,在 Lisp 中有特殊原因可以吗?

【问题讨论】:

    标签: arguments scheme lisp racket function-call


    【解决方案1】:

    名称list 不是保留关键字,它是一个普通函数。将名称重用于其他目的可能会使读者感到困惑,但不会给语言本身带来任何问题;这与在程序的不同部分拥有两个名为 x 的变量相同。

    【讨论】:

      【解决方案2】:

      主流 Lisp 后代和衍生产品(如 Commmon Lisp 和 Scheme)不包含保留关键字的概念。它与 Lisp 的工作方式完全不同。

      当扫描 Lisp 读取语法时,其中出现的标识符标记被转换为相应的符号对象。这些标记都属于同一个词法类别:符号。

      当 Lisp 读取语法被扫描并转换为对象时,例如表示程序代码的嵌套列表,这是在不考虑语义(符号含义)的情况下完成的。

      这与解析具有保留关键字的语言(例如宽泛的 Fortran/Algol 家族中的某些语言)不同。

      粗略地说,保留关键字是看起来像符号但实际上只是标点符号的标记。 Lisp 也有标点符号,如括号、尖号前缀、各种引号等。

      这些标点词在短语结构语法中具有固定的作用,必须对短语结构语法进行处理,才能考虑程序的语义。

      因此,例如,Pascal 中保留的 BEGINEND 关键字本质上只不过是冗长的括号。 '(' 和 ')' 标记在类似 Lisp 的语言中同样保留。在 Pascal 中尝试使用 BEGIN 作为函数或变量的名称类似于在 Lisp 中尝试使用 ( 作为函数或变量的名称。

      某些语言具有确定短语结构的关键字,但允许使用看起来与保留关键字完全一样的标识符。例如,PL/I 就因此而出名:

      IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF
      

      Lisp 方言可能会为某些符号或某些类别的符号分配特殊的语义处理。这是一种保留,但与保留关键字不完全相同,因为它处于语义级别。例如,在 Common Lisp 中,符号 nilt(更具体地说是 common-lisp 包中的 niltcommon-lisp:nilcommon-lisp:t)不能用作函数或变量名字。当其中任何一个作为表达式出现时,它都会计算自己:t 的值是 tnil 的值是 nil。此外,nil 也是布尔假值和空列表。因此,实际上,这些符号在某些方面是保留的。 Common Lisp 还有一个keyword 包。该包中的所有符号都对其自身进行评估,并且不得用作变量。它们可以用作函数名称,也可以用于任何其他目的。

      【讨论】:

        【解决方案3】:

        你说的是 Lisp,但答案会根据你所说的 Lisp 而有所不同。

        在 Common Lisp 中,您可以使用 list 作为变量,因为 Common Lisp 是 Lisp-2,这意味着每个符号都有一个单独的插槽用于函数绑定和变量绑定。 Common Lisp 为 CL 包中的符号 list 设置函数绑定,但不设置变量绑定。您不能更改函数绑定,因为 Common Lisp 不允许您重新定义在 CL 包中设置的符号的绑定(当然,您可以在自己的包中使用您喜欢的任何符号),但是由于变量绑定是免费的,你可以使用它。

        Scheme 是一个 Lisp-1,这意味着每个符号只有一个绑定。函数绑定和变量绑定没有分离(因此为什么在 Scheme 中使用 define,而在 CL 中使用 defundefvar)。您可以使用“列表”作为变量的原因是因为 Scheme 不会阻止您重新绑定其内置符号。这通常是个坏主意,因为通过重新定义list,您不能再调用list 函数。

        Emacs Lisp 是一个 Lisp-2,但不会阻止您重新绑定符号,这意味着您可以执行 (defun + (- a b)) 之类的操作,并且完全搞砸您的编辑会话。所以……不要那样做,除非你真的知道自己在做什么。

        Clojure 是一个 Lisp-1。我目前没有安装有效的 Clojure,所以我无法评论它可以让你做什么。我怀疑它比 Scheme 更严格。

        【讨论】:

        • 为了写下这个答案,我打开了 Emacs 并重新定义了+,正如我在评论中所说的那样。 Emacs 现在拒绝关闭。所以,是的,真的不要那样做。
        【解决方案4】:

        是的,令牌list 没有keyword 类型。

        当您想要定义自己的代数时,在 lisp 中通常会覆盖原语运算符或标准库运算符。

        【讨论】:

          猜你喜欢
          • 2012-06-28
          • 2020-02-02
          • 2019-01-09
          • 2014-03-08
          • 2011-07-10
          • 2020-05-23
          • 1970-01-01
          • 2020-05-24
          • 1970-01-01
          相关资源
          最近更新 更多