2010-11-08 18 views
6

¿Es posible enviar un mensaje anónimo a un objeto? Quiero componer tres objetos de este tipo (creo FP):Objetos de función en Smalltalk (o bloques de ejecución sin `valor:`)

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

donde reduce, applyToAll y transpose son objetos y +, * y las dos matrices son argumentos que se pasan a los mensajes anónimos enviados a esos objetos. ¿Es posible lograr el mismo uso de bloques? (pero no uso explícito de value:).

Respuesta

5
+0

pero si bien es posible que desee hacerlo, y puede, tal vez no debería. Al menos no para resolver este problema. –

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

funcionaría cuando aRealObject haya definido los métodos correctos. ¿Dónde necesitas un bloque?

3

que busca doesNotUnderstand:. Si reduce es un objeto que no implementa + pero lo envía de todos modos, entonces se invocará su método doesNotUnderstand:. Normalmente solo provoca un error. Pero puede anular el valor predeterminado, y acceder al selector + y el otro argumento y hacer lo que quiera con ellos.

Para simplificar, cree una clase Reduce. En su lado clase, definir el método:

doesNotUnderstand: aMessage 
    ^aMessage argument reduce: aMessage selector 

A continuación, se puede utilizar de esta manera:

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

que, en un espacio de trabajo responde a Squeak 32, como se esperaba.

Funciona porque * ya está implementado para Colecciones con semántica adecuada.

otra parte, añadir una clase ApplyToAll con este método del lado de clase:

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

y también añadir este método para SequenceableCollection:

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

A continuación, puede escribir

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

que está muy cerca de tu idea original.

Cuestiones relacionadas