在Lisp / Racket / Scheme中,如何有一个名为`list`的参数?

问题描述

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

解决方法

名称list不是保留关键字,它是一个普通函数。为其他目的而重用名称可能会使读者感到困惑,但不会对语言本身造成任何问题。就像在程序的不同部分中有两个名为x的变量一样。

,

主流Lisp的后代以及诸如Commmon Lisp和Scheme之类的派生词均未包含保留关键字的概念。它与Lisp的工作方式无关。

扫描Lisp读取语法时,其中显示的标识符标记将转换为相应的符号对象。这些标记都在同一词汇类别中:符号。

扫描Lisp读取语法并将其变成一个对象(例如表示程序代码的嵌套列表)时,无需考虑语义(符号的含义)。

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

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

这些标点符号在短语结构语法中具有固定的作用,必须先处理短语结构语法,然后才能考虑程序的语义。

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

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

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

Lisp方言可以为某些符号或符号的某些类别分配特殊的语义处理。这是一种保留,但与保留关键字并不完全相同,因为它是语义级别的。例如,在Common Lisp中,符号nilt(更具体地说是nil包中的tcommon-lispcommon-lisp:nilcommon-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软件包中设置的符号的绑定(当然,您可以在自己的软件包中使用所需的任何符号),但是由于变量绑定是免费的,您可以使用它。

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

Emacs Lisp是Lisp-2,但不会阻止您重新绑定符号,这意味着您可以执行(defun + (- a b))之类的操作,从而完全破坏了编辑会话。所以...除非您真的知道自己在做什么,否则不要这样做。

Clojure是Lisp-1。我目前尚无法安装Clojure,因此无法评论它可以做什么。我怀疑它比Scheme更严格。

,

是的,令牌list不具有keyword类型。

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