Функциональные объекты в SmallTalk (или выполнение блоков без `value:`)

StackOverflow https://stackoverflow.com/questions/4121786

Вопрос

Можно ли отправить анонимное сообщение на объект? Я хочу составить три подобных объекта (подумайте о FP):

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

куда reduce, applyToAll и transpose являются объектами и +, * и два массива - это аргументы, передаваемые анонимным сообщениям, отправленным этим объектам. Можно ли достичь того же, используя блоки? (но нет явного использования value:).

Другие советы

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

будет работать, когда Arealobject определил правильные методы. Где вам нужен блок?

Ты ищешь doesNotUnderstand:. Отказ Если reduce это объект, который не реализует + Но вы все равно отправляете его, тогда вместо этого это doesNotUnderstand: Метод будет вызван. Обычно это просто вызывает ошибку. Но вы можете переопределить по умолчанию и получить доступ к селектору + И другой аргумент и делайте с ними все, что вам нравится.

Для простоты создайте класс Reduce. Отказ На своем классе определите метод:

doesNotUnderstand: aMessage
    ^aMessage argument reduce: aMessage selector

Тогда вы можете использовать это так:

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

который в скрипечном рабочем пространстве отвечает 32, как и ожидалось.

Это работает, потому что * уже реализован для коллекций с подходящей семантикой.

В качестве альтернативы добавить класс ApplyToAll С этим методом класса:

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

а также добавить этот метод в SequenceableCollection:

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

Тогда вы можете написать

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

что довольно близко к вашей оригинальной идее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top