2010-11-08 9 views
6

Ist es möglich, eine anonyme Nachricht an ein Objekt zu senden? Ich möchte wie diese drei Objekte komponieren (man denke FP):Funktionsobjekte in Smalltalk (oder Ausführen von Blöcken ohne `Wert:`)

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

wo reduce, applyToAll und transpose Objekte sind und +, * und die beiden Arrays sind Argumente, um anonyme Nachrichten an diese Objekte weitergegeben gesendet. Ist es möglich, dieselben Blöcke zu verwenden? (aber keine explizite Verwendung von value:).

Antwort

5
+0

aber während Sie es vielleicht tun möchten und können, sollten Sie vielleicht nicht. Zumindest nicht um dieses Problem zu lösen. –

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

würde funktionieren, wenn aRealObject die richtigen Methoden definiert hat. Wo brauchst du einen Block?

3

Sie suchen doesNotUnderstand:. Wenn reduce ein Objekt ist, das + nicht implementiert, aber Sie senden es trotzdem, wird stattdessen die doesNotUnderstand:-Methode aufgerufen. Normalerweise wird nur ein Fehler ausgelöst. Aber Sie können den Standard überschreiben, und greifen Sie auf den Selektor + und das andere Argument und tun Sie, was Sie wollen mit ihnen.

Der Einfachheit halber erstellen Sie eine Klasse Reduce. Auf seiner Klasse Seite definieren Sie die Methode:

doesNotUnderstand: aMessage 
    ^aMessage argument reduce: aMessage selector 

Dann Sie es wie folgt verwenden können:

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

, die in einem Quietschen Arbeitsbereich 32 Antworten, wie erwartet.

Es funktioniert, weil * bereits für Sammlungen mit geeigneter Semantik implementiert ist.

Alternativ fügen Sie eine Klasse ApplyToAll mit dieser Klasse seitige Methode:

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

und fügen Sie diese Methode auch auf SequenceableCollection:

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

Dann können Sie schreiben

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

Das ist ziemlich nah an Ihrer ursprünglichen Idee.