Multiple Dispatch e CLOS

7

Non ho mai scritto software in Common Lisp, ma in Scheme e Clojure così come in C ++ e Python. Eppure ho dato un'occhiata al Common Lisp Object System (CLOS) in Common Lisp e Dylan. Ora, confrontandolo con OOP nella tradizione di Simula, CLOS e diciamo che il sistema di classe C ++ e Python ha il polimorfismo come tratto comune.

Sembrano differire nel modo in cui i dati e i metodi sono organizzati, nella famiglia Simula, i metodi sono parte integrante delle classi, sotto-voci se tu mentre con CLOS sono definiti al di fuori delle classi e sono procedure piuttosto generalizzate .

I sostenitori del Lisp in genere sostengono che i metodi virtuali nei linguaggi di programmazione della famiglia Simula sono piuttosto limitati poiché vengono invocati solo in base all'oggetto del primo argomento ( this o self ). Le funzioni generiche CLOS sono selezionate per diversi argomenti, quindi qualcosa di simile (pseudo codice)

method draw(c : Device, d : Drawable) ... 

può essere implementato per combinazioni arbitrarie Canvas e Drawable .

method draw(c : Printer, t : Triangle)....
method draw(c : Printer, t : Image)....
method draw(c : Screen, t : Image) ....

Nei linguaggi della famiglia Simula, ciò sarebbe più difficile, poiché draw dovrebbe essere associato alla famiglia di oggetti Device o Drawable . La soluzione canonica sembra essere il collegamento .

Dopo aver appreso CLOS, sono rimasto piuttosto sorpreso che la maggior parte dei linguaggi di programmazione OO non offrano dispacciamenti multipli e, se ci sono ragioni specifiche, perché si possano associare i metodi così strettamente a una classe specifica. Esistono vantaggi specifici per la singola spedizione?

  • ambiguità di invio multiplo: diciamo che ho a sottoclasse A e b sottoclasse B . Il metodo foo(A,B) implementato come foo(a,B) e foo(A,b) , quale implementazione richiama una chiamata di foo(a,b) ? È questa l'unica ragione?
  • "Modularizzazione", i metodi nella classe sono vicini.

C'è dell'altro? I designer di lingue e i creatori hanno preso una posizione in merito?

    
posta wirrbel 27.08.2013 - 21:42
fonte

3 risposte

3

La distribuzione singola è in qualche modo più semplice da implementare e in pratica è raramente necessaria la distribuzione multipla secondo la ricerca di Muschevici et al.

Puoi trovare ulteriori informazioni nell'articolo Wikipedia su più spedizioni ; ad esempio, spiega anche perché il metodo CLOS di definizione dei metodi multimodali può essere più adatto per la sintassi estremamente uniforme di Lisp, piuttosto che per il più frequente nidificazione di metodi all'interno delle classi.

    
risposta data 27.08.2013 - 21:49
fonte
5

Ora esistono diverse lingue che supportano la distribuzione multipla. Ci sono estensioni per alcuni. Perl / Moose, Dylan, Julia , ...

Il linguaggio di invio orientato agli oggetti ha alcune cose che possono essere viste come un vantaggio:

  • una classe può essere uno spazio dei nomi. Nelle classi CLOS non sono spazi dei nomi.

  • I metodi
  • possono trovarsi in uno spazio dei nomi di classe. Nei metodi CLOS non sono in uno spazio dei nomi di classe. Per avere accesso più breve a variabili e accessor, CLOS utilizza macro WITH-SLOTS e WITH-ACCESSORS .

  • in un sistema di passaggio di classe / messaggio, tutti i messaggi possono essere inoltrati a un altro oggetto con una singola azione.

  • una classe potrebbe avere un gestore per tutti i messaggi che non capisce. In CLOS questo sembrerebbe un po 'più difficile.

  • le prestazioni potrebbero essere un problema in un sistema simile a CLOS a causa del mix di multi-metodi e ereditarietà multipla.

  • l'organizzazione del codice sorgente e i metodi di ricerca potrebbero essere più difficili o almeno diversi in un sistema simile a CLOS.

risposta data 30.08.2013 - 22:37
fonte
2

Oltre la "modularità", una conseguenza di un metodo associato (o appartenente) a un oggetto è la sua autonomia nel scegliere come rispondere a un messaggio (e "viaggiare" con il proprio comportamento). Con il multi-dispatch come trovato in questi linguaggi, hai un meccanismo globale sottostante che esegue il binding e decide come eseguire il calcolo.

    
risposta data 29.08.2013 - 19:34
fonte