2017-01-04 15 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 

В примерах выше, вы можете увидеть методы сами никогда не используют x или y переменные. Это совпадение, что все эти примеры никогда не используют переменные? Можно ли их использовать?

Кроме того, это написано на Wikipedia:

методы определяются отдельно от классов, и они не имеют никакого специального доступа (например, «этот», «я», или «защищенный») для класса слотов.

Хорошо, поэтому методы не имеют «этого», потому что они не относятся к классу. Но почему методы обобщенной функции могут иметь приемник? Разве приемник не похож на «это» в классе?

ответ

5

Уверен, что вы можете получить доступ к переменным из списка параметров. Пример wikipedia только для иллюстрации того, какой метод возвращает значение.

Но почему методы общей функции имеют приемник тогда? Разве приемник не похож на «это» в классе?

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

Это сделало все ясно! Приемник - просто аргумент. Конечно! Благодаря! –

3

В примерах показано, как диспетчерские работы основаны на типах, поэтому они не удосуживаются использовать переменные. Но вы, конечно, могли бы, например,

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

(f 3 'foo) => 9 

Использование приемника просто условность. Если вы хотите использовать CLOS аналогично другим языкам ООП, вы можете просто отправить тип первого аргумента. И вы могли бы назвать это this или self, чтобы сделать намерение понятным.