2010-11-08 13 views
6

È possibile inviare un messaggio anonimo a un oggetto? Voglio comporre tre oggetti come questo (si pensi FP):Oggetti funzione in Smalltalk (o blocchi in esecuzione senza valore `::)

" find inner product " 
reduce + (applyToAll * (transpose #(1 2 3) #(4 5 6))) 

dove reduce, applyToAll e transpose sono oggetti e +, * e le due matrici sono argomenti passati ai messaggi anonimi inviati a quegli oggetti. È possibile ottenere lo stesso usando i blocchi? (ma nessun uso esplicito di value:).

risposta

5
+0

ma mentre si potrebbe desiderare di farlo, e può, forse non si dovrebbe. Almeno per non risolvere questo problema. –

5
aRealObject reduceMethod: +; 
      applyToAll: *; 
      transpose: #(#(1 2 3) #(4 5 6)); 
      evaluate 

funzionerebbe quando aRealObject ha definito i metodi corretti. Dove hai bisogno di un blocco?

3

siete alla ricerca di doesNotUnderstand:. Se reduce è un oggetto che non implementa + ma lo si invia comunque, verrà invece richiamato il suo metodo doesNotUnderstand:. Normalmente solleva un errore. Ma puoi ignorare il valore predefinito e accedere al selettore + e l'altro argomento e fare quello che vuoi con loro.

Per semplicità, creare una classe Reduce. Da parte sua classe, definire il metodo:

doesNotUnderstand: aMessage 
    ^aMessage argument reduce: aMessage selector 

quindi è possibile utilizzare in questo modo:

Reduce + (#(1 2 3) * #(4 5 6)) 

che, in uno spazio di lavoro Squeak risponde 32, come previsto.

Funziona perché * è già implementato per le raccolte con semantica adatta.

In alternativa, aggiungere una classe ApplyToAll con questo metodo di classe-side:

doesNotUnderstand: aMessage 
    ^aMessage argument collect: [:e | e reduce: aMessage selector] 

e anche aggiungere questo metodo per SequenceableCollection:

transposed 
    ^self first withIndexCollect: [:c :i | self collect: [:r | r at: i]] 

Poi si può scrivere

Reduce + (ApplyToAll * #((1 2 3) #(4 5 6)) transposed) 

che è abbastanza vicino alla tua idea originale.