2010-11-08 32 views
6

Est-il possible d'envoyer un message anonyme à un objet? Je veux composer trois objets comme celui-ci (pensez FP):Objets fonctionnels dans Smalltalk (ou exécution de blocs sans valeur: `)

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

reduce, applyToAll et transpose sont des objets et +, * et les deux tableaux sont les arguments transmis aux messages anonymes envoyés à ces objets. Est-il possible de réaliser la même chose en utilisant des blocs? (mais pas d'utilisation explicite de value:).

Répondre

5
+0

mais alors que vous pourriez vouloir le faire, et peut, peut-être vous ne devriez pas. Au moins ne pas résoudre ce problème. –

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

fonctionnerait quand aRealObject a défini les bonnes méthodes. Où avez-vous besoin d'un bloc?

3

Vous êtes à la recherche de doesNotUnderstand:. Si reduce est un objet qui n'implémente pas + mais que vous l'envoyez de toute façon, sa méthode doesNotUnderstand: sera appelée. Normalement, cela provoque simplement une erreur. Mais vous pouvez remplacer la valeur par défaut, et accéder au sélecteur + et l'autre argument et faire ce que vous voulez avec eux.

Pour plus de simplicité, créez une classe Reduce. De son côté classe, définir la méthode:

doesNotUnderstand: aMessage 
    ^aMessage argument reduce: aMessage selector 

Ensuite, vous pouvez l'utiliser comme ceci:

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

qui, dans un espace de travail répond Squeak 32, comme prévu.

Cela fonctionne car * est déjà implémenté pour les collections avec une sémantique appropriée.

Vous pouvez également ajouter une classe ApplyToAll avec cette méthode classe côté:

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

et ajouter cette méthode pour SequenceableCollection:

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

Ensuite, vous pouvez écrire

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

ce qui est assez proche de votre idée originale.