2

我正在学习 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

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

此外,它写在Wikipedia上:

方法与类分开定义,它们对类槽没有特殊的访问权限(例如“this”、“self”或“protected”)。

好的,所以方法没有“this”,因为它们不属于一个类。但是为什么泛型函数方法可以有一个接收器呢?接收器不是类似于类中的'this'吗?

4

2 回答 2

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"

您会看到这两个变量s1s2被使用了。命名其中之一是没有意义的receiver

但是您可以随意命名变量,并且当您的应用程序仅对第一个参数使用分派时,您可能希望调用该变量receiver,但该名称对于 CLOS 没有语义。这只是另一个名字。

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

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

(defmethod plus ((receiver string) (argument string))
   (concatenate 'string receiver argument))

这更有用:

(defmethod plus ((string-1 string) (string-2 string))
   (concatenate 'string string-1 string-2))
于 2017-01-04T23:38:22.770 回答
3

这些示例只是展示了基于类型的分派是如何工作的,因此它们不会费心使用变量。但你当然可以,例如

(defmethod f ((x integer) (y symbol))
    (* x x))

(f 3 'foo) => 9

接收器的使用只是一种约定。如果您想像使用其他 OOP 语言一样使用 CLOS,您可能只需发送第一个参数的类型。您可以调用它thisself明确意图。

于 2017-01-04T23:32:19.320 回答