2017-01-04 29 views
2

我正在學習CLOS中的泛型函數。不能在泛型函數方法中使用變量嗎? (CLOS/LISP)

由於我在教科書和在線中找到的例子類型,我感到非常困惑。這些例子總是使用有多個派遣的事實。根據參數類型,執行不同的計算。但是,爲什麼這些論據本身從未在例子中被使用?

實施例的代碼從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 

在上述示例中,可以看到該方法本身實際上從未使用xy變量。所有這些例子都不使用變量是巧合嗎?他們可以用嗎?

此外,它是寫在Wikipedia

方法是從類分開定義,他們有沒有特殊的訪問(例如,「這個」,「自我」,或「受保護」),以一流的插槽。

好的,所以方法沒有「this」,因爲它們不屬於一個類。但爲什麼泛型函數方法有一個接收器呢?接收器是不是類似於課堂上的「這個」?

回答

5

確定您可以從參數列表中訪問變量。維基百科示例僅用於說明哪個方法返回值。

但是爲什麼泛型函數方法有接收器呢?接收器是不是類似於課堂上的「這個」?

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)) 
+0

這讓這一切清楚了!接收器只是一個參數..當然!謝謝! –

3

這些示例僅顯示調度如何基於類型工作,因此他們不打擾使用變量。但你當然可以,例如

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

(f 3 'foo) => 9 

的使用接收機的僅僅是一個慣例。如果您想要像其他OOP語言一樣使用CLOS,則可以僅派發第一個參數的類型。你可以稱它爲thisself以使意圖清晰。

相關問題