【发布时间】:2020-09-14 05:59:20
【问题描述】:
list 不是在 Lisp 中创建新列表的 关键字,但在 Lisp 中可以有一个名为 list 的参数。我认为大多数编程语言(如 Java 或 C++)中的关键字不能用于 argument names,在 Lisp 中有特殊原因可以吗?
【问题讨论】:
标签: arguments scheme lisp racket function-call
list 不是在 Lisp 中创建新列表的 关键字,但在 Lisp 中可以有一个名为 list 的参数。我认为大多数编程语言(如 Java 或 C++)中的关键字不能用于 argument names,在 Lisp 中有特殊原因可以吗?
【问题讨论】:
标签: arguments scheme lisp racket function-call
名称list 不是保留关键字,它是一个普通函数。将名称重用于其他目的可能会使读者感到困惑,但不会给语言本身带来任何问题;这与在程序的不同部分拥有两个名为 x 的变量相同。
【讨论】:
主流 Lisp 后代和衍生产品(如 Commmon Lisp 和 Scheme)不包含保留关键字的概念。它与 Lisp 的工作方式完全不同。
当扫描 Lisp 读取语法时,其中出现的标识符标记被转换为相应的符号对象。这些标记都属于同一个词法类别:符号。
当 Lisp 读取语法被扫描并转换为对象时,例如表示程序代码的嵌套列表,这是在不考虑语义(符号含义)的情况下完成的。
这与解析具有保留关键字的语言(例如宽泛的 Fortran/Algol 家族中的某些语言)不同。
粗略地说,保留关键字是看起来像符号但实际上只是标点符号的标记。 Lisp 也有标点符号,如括号、尖号前缀、各种引号等。
这些标点词在短语结构语法中具有固定的作用,必须对短语结构语法进行处理,才能考虑程序的语义。
因此,例如,Pascal 中保留的 BEGIN 和 END 关键字本质上只不过是冗长的括号。 '(' 和 ')' 标记在类似 Lisp 的语言中同样保留。在 Pascal 中尝试使用 BEGIN 作为函数或变量的名称类似于在 Lisp 中尝试使用 ( 作为函数或变量的名称。
某些语言具有确定短语结构的关键字,但允许使用看起来与保留关键字完全一样的标识符。例如,PL/I 就因此而出名:
IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF
Lisp 方言可能会为某些符号或某些类别的符号分配特殊的语义处理。这是一种保留,但与保留关键字不完全相同,因为它处于语义级别。例如,在 Common Lisp 中,符号 nil 和 t(更具体地说是 common-lisp 包中的 nil 和 t,common-lisp:nil 和 common-lisp:t)不能用作函数或变量名字。当其中任何一个作为表达式出现时,它都会计算自己:t 的值是 t,nil 的值是 nil。此外,nil 也是布尔假值和空列表。因此,实际上,这些符号在某些方面是保留的。 Common Lisp 还有一个keyword 包。该包中的所有符号都对其自身进行评估,并且不得用作变量。它们可以用作函数名称,也可以用于任何其他目的。
【讨论】:
你说的是 Lisp,但答案会根据你所说的 Lisp 而有所不同。
在 Common Lisp 中,您可以使用 list 作为变量,因为 Common Lisp 是 Lisp-2,这意味着每个符号都有一个单独的插槽用于函数绑定和变量绑定。 Common Lisp 为 CL 包中的符号 list 设置函数绑定,但不设置变量绑定。您不能更改函数绑定,因为 Common Lisp 不允许您重新定义在 CL 包中设置的符号的绑定(当然,您可以在自己的包中使用您喜欢的任何符号),但是由于变量绑定是免费的,你可以使用它。
Scheme 是一个 Lisp-1,这意味着每个符号只有一个绑定。函数绑定和变量绑定没有分离(因此为什么在 Scheme 中使用 define,而在 CL 中使用 defun 和 defvar)。您可以使用“列表”作为变量的原因是因为 Scheme 不会阻止您重新绑定其内置符号。这通常是个坏主意,因为通过重新定义list,您不能再调用list 函数。
Emacs Lisp 是一个 Lisp-2,但不会阻止您重新绑定符号,这意味着您可以执行 (defun + (- a b)) 之类的操作,并且完全搞砸您的编辑会话。所以……不要那样做,除非你真的知道自己在做什么。
Clojure 是一个 Lisp-1。我目前没有安装有效的 Clojure,所以我无法评论它可以让你做什么。我怀疑它比 Scheme 更严格。
【讨论】:
+,正如我在评论中所说的那样。 Emacs 现在拒绝关闭。所以,是的,真的不要那样做。
是的,令牌list 没有keyword 类型。
当您想要定义自己的代数时,在 lisp 中通常会覆盖原语运算符或标准库运算符。
【讨论】: