在泛型函数方法中不能使用变量吗?(CLOS/LISP)

Kev*_*gem 2 lisp common-lisp clos generic-function

我正在学习CLOS中的泛型函数.

由于我在教科书和网上找到的例子类型,我变得非常困惑.这些示例总是使用多个调度的事实.根据参数类型,执行不同的计算.但是,为什么参数本身从未在示例中使用过?

维基百科的示例代码

; declare the common argument structure prototype
(defgeneric f (x y)) 

; define an implementation for (f integer t), where t matches all types
(defmethod f ((x integer) y) 1) 

(f 1 2.0) => 1

; define an implementation for (f integer real)
(defmethod f ((x integer) (y real)) 2) 

(f 1 2.0) => 2 ; dispatch changed at runtime
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,您可以看到方法本身从未实际使用过xy变量.所有这些例子都不使用变量,这是巧合吗?他们可以用吗?

此外,它写在维基百科上:

方法与类分开定义,并且它们对类槽没有特殊访问权(例如"this","self"或"protected").

好吧,所以方法没有"这个",因为它们不属于一个类.但是为什么泛型函数方法有接收器呢?接收器在类中不是类似于'this'吗?

Rai*_*wig 5

当然,您可以从参数列表中访问变量.维基百科示例仅用于说明哪个方法返回值.

但是为什么泛型函数方法有接收器呢?接收器在类中不是类似于'this'吗?

CLOS泛型函数没有单个接收器,因此使用单词接收器是没有意义的.您提到的实现可能没有实现完整的CLOS,而是没有多个调度的变体.

CLOS示例:

CL-USER 8 > (defmethod plus ((s1 string) (s2 string))
              (concatenate 'string s1 s2))
#<STANDARD-METHOD PLUS NIL (STRING STRING) 4020001E6B>

CL-USER 9 > (plus "foo" "bar")
"foobar"
Run Code Online (Sandbox Code Playgroud)

您将看到两个变量s1s2使用.为其中一个命名是没有意义的receiver.

但是您可以根据需要命名变量,当应用程序仅使用第一个参数的调度时,您可能希望调用该变量receiver,但该名称对CLOS没有语义.这只是另一个名字.

通常对于CLOS代码,最好给参数提供有用的名称.

这是误导性的,因为我们没有在CLOS中传递消息:

(defmethod plus ((receiver string) (argument string))
   (concatenate 'string receiver argument))
Run Code Online (Sandbox Code Playgroud)

这更有用:

(defmethod plus ((string-1 string) (string-2 string))
   (concatenate 'string string-1 string-2))
Run Code Online (Sandbox Code Playgroud)