不能在泛型函数方法中使用变量吗? (CLOS/LISP)
Can't variables be used within generic function methods? (CLOS/LISP)
我正在学习 CLOS 中的通用函数。
由于我在教科书和网上找到的示例类型,我感到非常困惑。这些示例始终使用存在多个分派的事实。根据参数类型,执行不同的计算。但是,为什么示例中从未使用过参数本身?
Example code from Wikipedia
; 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
在上面的示例中,您可以看到方法本身从未实际使用 x
或 y
变量。所有这些示例从不使用变量是巧合吗?可以用吗?
还有,写在Wikipedia:
Methods are defined separately from classes, and they have no special access (e.g. "this", "self", or "protected") to class slots.
好的,所以方法没有 "this" 因为它们不属于 class。但是为什么泛型函数方法可以有一个接收者呢? class中的'this'不是receiver吗?
这些示例只是展示了如何根据类型进行分派,因此他们不必费心使用变量。但是你当然可以,例如
(defmethod f ((x integer) (y symbol))
(* x x))
(f 3 'foo) => 9
接收器的使用只是一种约定。如果您想像使用其他 OOP 语言一样使用 CLOS,您可能只根据第一个参数的类型进行分派。您可以将其命名为 this
或 self
以明确意图。
当然可以从参数列表中访问变量。维基百科示例仅用于说明哪种方法 returns 值。
But why can generic-function methods have a receiver then? Isn't the receiver similar to the 'this' in a class?
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"
您看到使用了变量 s1
和 s2
。将其中之一命名为 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))
我正在学习 CLOS 中的通用函数。
由于我在教科书和网上找到的示例类型,我感到非常困惑。这些示例始终使用存在多个分派的事实。根据参数类型,执行不同的计算。但是,为什么示例中从未使用过参数本身?
Example code from Wikipedia
; 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
在上面的示例中,您可以看到方法本身从未实际使用 x
或 y
变量。所有这些示例从不使用变量是巧合吗?可以用吗?
还有,写在Wikipedia:
Methods are defined separately from classes, and they have no special access (e.g. "this", "self", or "protected") to class slots.
好的,所以方法没有 "this" 因为它们不属于 class。但是为什么泛型函数方法可以有一个接收者呢? class中的'this'不是receiver吗?
这些示例只是展示了如何根据类型进行分派,因此他们不必费心使用变量。但是你当然可以,例如
(defmethod f ((x integer) (y symbol))
(* x x))
(f 3 'foo) => 9
接收器的使用只是一种约定。如果您想像使用其他 OOP 语言一样使用 CLOS,您可能只根据第一个参数的类型进行分派。您可以将其命名为 this
或 self
以明确意图。
当然可以从参数列表中访问变量。维基百科示例仅用于说明哪种方法 returns 值。
But why can generic-function methods have a receiver then? Isn't the receiver similar to the 'this' in a class?
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"
您看到使用了变量 s1
和 s2
。将其中之一命名为 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))