2015-04-15 13 views
5

Ho notato, alla lettura del libro di Keene, che defgeneric ha un'opzione :method, che sembra come se consentisse di specificare un metodo nella definizione generica stessa. La maggior parte della documentazione che ho visto ha tutti i metodi applicabili definiti in separati defmethod s. Lo hyperspec, con la sua solita chiarezza, elenca :method come opzione per defgeneric, ma non dice cosa significa.Uso di: opzione di metodo in defgeneric

L'opzione :method presenta un valore predefinito, o almeno, documenta ciò che si prevede che il caso d'uso più comune sarà o ha semantica aggiuntiva? Come punto di stile, se si prevede di definire un solo metodo, ha più senso definirlo nel formato defgeneric (se è possibile farlo effettivamente) o separatamente in un defmethod? O non ha senso fare una funzione generica in questo caso e utilizzare invece un normale defun?

risposta

6

Il hyperspec, con la consueta chiarezza, elenchi: Metodo come opzione per defgeneric, ma non dice cosa significa.

In realtà, la HyperSpec entry for defgeneric, con la consueta chiarezza, dice esattamente che cosa significa. Dice che la sintassi di defgeneric è:

defgeneric nome-funzione gf-lambda-list [[opzione | {Metodo-description} *]]

e poi dice che la sintassi per il metodo-descrizione è:

metodo-descrizione :: = (: il metodo Metodo-qualificazione * specializzato-lambda-list [[dichiarazione * | documentazione]] forma *)

E poi descrive metodo-combinazione:

Ogni descrizione del metodo definisce un metodo sulla funzione generica. L'elenco lambda di ciascun metodo deve essere congruente con l'elenco lambda specificato dall'opzione gf-lambda-list. Se nessuna descrizione del metodo è specificata e una funzione generica con lo stesso nome non esiste già , viene creata una funzione generica senza metodi.

Così il: metodo di forme sono per definire metodi sulla funzione generica, proprio come defmethod forme.

(concederò che in realtà non dice nulla circa il motivo per cui si preferisce più defgeneric: metodo al contrario di defmethod ricordare che il Comune in Common Lisp significa che la lingua è un tentativo di unificare. molte delle implementazioni Lisp esistenti. Forse alcune supportate: metodo e altre supportate da defmethod, e questo era il modo più semplice per fornire un'interfaccia unificata.)

Cioè, la seguente avrebbe lo stesso effetto:

(defgeneric to-list (object)) 

(defmethod to-list ((object t)) 
    (list object)) 

(defmethod to-list ((object list)) 
    object) 

(defgeneric to-list (object) 
    (:method ((object t)) 
    (list object)) 
    (:method ((object list)) 
    object)) 

volte può essere conveniente definire alcuni dei metodi con il modulo defgeneric. È più una questione di stile, e questo entra nelle altre parti della tua domanda.

fa il: opzione del metodo di presentare un difetto, o almeno, documentare ciò si aspetta il caso d'uso più comune sarà, o ha semantica supplementari?

può essere una sorta di default, se si definisce un metodo senza specificatori di tipo, o con specificatori di tipo che si applicano a tutti gli oggetti (ad esempio, t).

Come punto di stile, se si prevede di definire un solo metodo, fa più senso per definire nella forma defgeneric (se è possibile, anzi, farlo), o separatamente in un defmethod ? Oppure non è il senso di senso fare una funzione generica in questo caso, e invece utilizzare un defun regolare?

Penso che dipenda dal motivo per cui si prevede di definire un solo metodo. Se è perché si sta solo definendo un valore predefinito, ma si aspettano che altri utenti implementino i metodi su di esso, inserire i metodi insieme a defmethod potrebbe essere utile se qualcuno ha bisogno di trovare la fonte. Se ti aspetti che ci sia solo una cosa da fare, allora una funzione normale potrebbe avere più senso. Penso che queste decisioni si riducano a scelte di stile.

Vale anche la pena notare che ci sono altre forme che possono definire metodi su una funzione generica (e altre forme che possono produrre anche funzioni generiche). In HyperSpec, usare le frecce su per andare alle sezioni più alte ti porterà di solito a più prose. In questo caso, è utile 7.6.1 Introduction to Generic Functions:

Alcuni operatori definiscono metodi per una funzione generica. Questi operatori saranno indicati come operatori che definiscono il metodo; i loro moduli associati sono chiamati moduli di definizione del metodo. Gli operatori di definizione dei metodi standardizzati sono elencati nella figura seguente.

defgeneric  defmethod defclass 
define-condition defstruct 
+0

CLOS era basato principalmente su Flavours/New Flavors e LOOPS/CommonLOOPS. Molti metodi possono essere lunghi e di solito non è opportuno inserirne alcuni all'interno di un modulo lungo. Anche un solo metodo rende la ridefinizione del tipo più facile/veloce ... –

+0

Grazie. Forse l'iperspec è pensato per le persone con occhi migliori dei miei. (Non posso credere che io abbia lasciato un "è" lì quando intendo "suo".) – amp108

+0

@ amp108 Ci sono in realtà alcune altre forme che introducono metodi su funzioni generiche (e in alcuni casi introducono anche le funzioni generiche). Alcune parti in prosa dell'iperspec discutono di questo; Alla fine ho aggiornato la mia risposta con un paragrafo. –

2

E 'fino a preferenze personali e che cosa come il sistema sarebbe organizzata in fonte.Sia

  • semplice funzione generica: un mazzo di DEFMETHODS

  • complessa funzione generica: un DEFGENERIC e un gruppo di DEFMETHODS

  • funzione generica: un DEFGENERIC e un gruppo di metodi all'interno

La maggior parte dei sistemi OO Lisp prima che CLOS usasse il singl e modulo di definizione del metodo. Il codice potrebbe essere troppo lungo in una forma, altrimenti le funzioni generiche non esistevano per lo più, ...

Con i sistemi di distribuzione singola orientati alla classe, avrebbe potuto essere sensato organizzare i metodi in una definizione di classe. Con l'introduzione di funzioni generiche e invio multiplo aveva senso organizzarli sotto una definizione di funzione generica.