问题描述
不是list
的关键字在Lisp中创建新列表,但是在Lisp中可能有一个名为list
的参数。我以为Java或C ++等大多数编程语言中的关键字不能用于 argument names ,在Lisp中是否有可以使用的特殊原因?
解决方法
名称list
不是保留关键字,它是一个普通函数。为其他目的而重用名称可能会使读者感到困惑,但不会对语言本身造成任何问题。就像在程序的不同部分中有两个名为x
的变量一样。
主流Lisp的后代以及诸如Commmon Lisp和Scheme之类的派生词均未包含保留关键字的概念。它与Lisp的工作方式无关。
扫描Lisp读取语法时,其中显示的标识符标记将转换为相应的符号对象。这些标记都在同一词汇类别中:符号。
扫描Lisp读取语法并将其变成一个对象(例如表示程序代码的嵌套列表)时,无需考虑语义(符号的含义)。
这与具有保留关键字的语言(例如广泛的Fortran / Algol系列中的某些语言)的解析不同。
粗略地说,保留关键字是看起来像符号但实际上只是标点符号的令牌。 Lisp也具有标点符号,例如括号,sharpsign前缀,各种引号等。
这些标点符号在短语结构语法中具有固定的作用,必须先处理短语结构语法,然后才能考虑程序的语义。
因此,例如,Pascal中保留的BEGIN
和END
关键字本质上不过是冗长的括号。类似地,在类似Lisp的语言中保留'(
和')
'标记。在Pascal中尝试使用BEGIN
作为函数或变量的名称类似于在Lisp中尝试使用(
作为函数或变量的名称。
某些语言具有确定短语结构的关键字,但无论如何仍允许使用看起来与保留关键字完全一样的标识符。例如,PL / I为此而闻名:
IF IF=THEN THEN THEN=ELSE; ELSE ELSE=IF
Lisp方言可以为某些符号或符号的某些类别分配特殊的语义处理。这是一种保留,但与保留关键字并不完全相同,因为它是语义级别的。例如,在Common Lisp中,符号nil
和t
(更具体地说是nil
包中的t
和common-lisp
,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软件包中设置的符号的绑定(当然,您可以在自己的软件包中使用所需的任何符号),但是由于变量绑定是免费的,您可以使用它。
方案是Lisp-1,这意味着每个符号只有一个绑定。函数绑定和变量绑定没有分隔(因此,为什么在Scheme中使用define
,而在CL中使用defun
和defvar
)。之所以可以将“列表”用作变量,是因为Scheme不会阻止您重新绑定其内置符号。通常这是一个坏主意,因为通过重新定义list
您将无法再调用list
函数。
Emacs Lisp是Lisp-2,但不会阻止您重新绑定符号,这意味着您可以执行(defun + (- a b))
之类的操作,从而完全破坏了编辑会话。所以...除非您真的知道自己在做什么,否则不要这样做。
Clojure是Lisp-1。我目前尚无法安装Clojure,因此无法评论它可以做什么。我怀疑它比Scheme更严格。
,是的,令牌list
不具有keyword
类型。
当想要定义自己的代数时,通常会覆写原语运算符或标准库运算符。