2015-08-08 7 views
7

Предположим, что у меня есть объект, x, который может принимать любой из селекторов, s1, s2, ..., sn. Предположим далее, что результатом любого из этих селекторов, работающих на объекте, является обновленный объект того же типа. Я мог бы тогда «цепь» эти селекторы (до тех пор, как они унарные сообщения), как я хочу, такие как:Цепочные сообщения ключевых слов

x s1 s2 ... sn 

Это займет результат x s1 и применить селектор s2, а затем применить селектор s3 к этот результат и т. д. Я хотел бы применить один или более из этих селекторов в определенном порядке для различных результатов:

x s8 s2 

В Smalltalk я могу это сделать, если селекторы унарными сообщений. Однако, если мои селекторы - это сообщения с ключевыми словами, я больше не могу этого делать. Если x индивидуально принимает селекторы, s1:, s2:, ..., sn:, то следующее не работает:

x s1: a1 s2: a2 ... sn: an 

Существует ; оператор:

x s1: a1 ; s2: a2 ; ... ; sn: an 

Но используя каскадные : каждый этап изменяет оригинал x по пути, и в этом случае я не хочу изменять x.

Для сообщений по ключевым словам цепи, я думаю, что я оставил, используя следующий синтаксис с помощью скобок:

(...(((x s1: a1) s2: a2) ... sn: an) 

Что заставляет меня чувствовать, что я программирование в LISP, если у меня есть 3 или более keywrod сообщений. Конкретным примером этого может быть многомерный массив. Если foo является 3 одномерный массив, и вы хотите получить доступ к объекту в месте 2,3,5 в массиве, я думаю, что это будет выглядеть так:

(((foo at: 2) at: 3) at: 5) some_object_selectors 

Это тривиальный пример, конечно, но иллюстрирует случай. У вас могут быть другие типы встроенных объектов или другая цепочка последовательных операций с объектами, в которых вас интересует конечный результат.

Есть ли более синтаксически привлекательный способ сделать это в Smalltalk? Я предположив нет другого оператора, возможно, кузен к оператору ; (скажем, мы используем &, например), который бы приковать их, такие как:

x s1: a1 & s2: a2 & ... & sn: an 

Так как я хотел бы применить селекторы в любом или почти любом желаемом порядке (для, возможно, разных результатов), селекторная форма, s1:s2:s3:... слишком ограничена. Кроме того, это дает объект, который уже существует в других языках, таких как Ruby, где было бы то же самое выражается как:

x.s1(a1).s2(a2)...sn(an) 

Не имея специального оператора, альтернативой может быть, чтобы передать массив пар селектора аргументов , или, возможно, таблицу поиска пар пар селектора.Таблица поиска требует установки для прохождения литералов (он должен быть создан и заполнен), что заставляет меня склоняться к массиву, так как я могу просто написать:

x { {s1. a1}. {s2. a2}. ... {sn. an} } 

Это еще немного неуклюжим, и я m не настолько уверен, что это более элегантно, чем просто использовать все круглые скобки. Я боюсь, что мой вопрос может быть, по крайней мере, частично субъективным, но мне интересно узнать, что может быть лучшей практикой, и существует ли оператор, о котором я не знаю, что может помочь, или же кто-то развлекается Smalltalk нормативный орган.

+0

Хороший вопрос, также иногда выражаемый как трубка сообщения или конвейер - ваш не первый, кто пропустил такую ​​функцию, он регулярно обсуждается в списке рассылки. Я рекомендую отличный блог http://blog.3plus4.org/2007/08/30/message-chains/ –

+0

@ aka.nice Да, похоже, они избили меня до 8 лет назад. :) – lurker

ответ

1

Обычно мы предоставляем этот объект x субъекту для работы, а затем запрашиваем этот измененный предмет, когда мы закончим с ним. Копирование довольно неэффективно.

Object subclass: #Foo 
    instanceVariableNames: 'subject' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'Try' 

order: y 
    self subject order: y 

select: z 
    self subject select: z 

subject 
    ^subject ifNil: [ subject := FooSubject new ] 

where: x 
    self subject where: x 
+0

Я понимаю. Я искал способ получить тот же эффект, что и x.s1 (a1) .s2 (a2) ... sn (an), как это сделано в Ruby, например, без необходимости использовать все круглые скобки. Объект x - это то, что я могу использовать для разных операций в разное время с разными наборами селекторов. Поэтому я не хочу его менять. Если он изменится, тогда я должен сделать его копии в любом случае, поэтому я снова его в оригинальной форме.Если я хочу сохранить объект, на котором выполняется некоторое количество операций, я бы сделал это, используя 'newX: = x s1: a1 | s3: a3.' например. – lurker

+0

Что вы пытаетесь достичь? Я не уверен, как написать понятный код с этой конструкцией. –

+0

Этот вид конструкции используется повсеместно в Ruby on Rails. При построении запросов с помощью 'ActiveRecord' можно делать такие вещи, как:' Foo.where (...). Order (...). Select (...) 'but' Foo' не изменяется. Семантика кода понятна. Возможно, в этом случае, в Paradime Smalltalk, мне нужно просто сделать копию 'Foo' каждый раз и позволить операторам модифицировать ее. Я должен буду подумать об этом. – lurker

8

Здесь, кажется, есть путаница.

  1. Каскадные осуществляется с помощью ;, где каждое сообщение посылается в тот же аргумент.
  2. Вашего x s1 s2... примера (который вы называетесь «каскадный») называется сообщением цепочки, где каждое сообщение посылаются к результату предыдущего сообщения (из-за красивую и элегантную природу синтаксиса Smalltalk, который является просто Object message и всегда возвращает результат). И нет, вы не можете всегда ставить их в любом порядке. Представьте, что s1 - multiplyByTwo и s2 - addTwo, с x, имеющий переменную экземпляра, модифицированную этими методами, которая начинается с 1. Заказ может иметь значение. (Обратите внимание, что я очень неохотно использую такие ужасно короткие имена в качестве примеров - это не очень Smalltalk-like. ;-)
  3. Если ваш n настолько велик, что с помощью круглых скобок это выглядит неудобно, тогда, мм ... извините, но вы делаете это неправильно.
    • Рассмотрите возможность создания метода на вашем объекте для принятия нескольких аргументов.
    • Рассмотрите возможность создания объекта-обертки для переноса параметров.
    • Рассмотрите возможность использования шаблона проектирования, чтобы отделить объект от операций, которые вы хотите выполнить на нем. (Какой шаблон вам нужно будет зависеть от того, что вы хотите достичь;. here's a good starting point)

Вместо того, чтобы искать оператор согнуть Smalltalk вашего желания (как вы можете использовать, чтобы делать вещи в других языки), я бы рекомендовал вместо этого использовать гибкую схему для Smalltalk (явное присвоение имен, не боясь создавать больше объектов и методов и т. д.). В конечном итоге вы получите больше от этого, и я смею сказать, что вы доберетесь до того, что хотите, чтобы на другом языке была простота и сила Smalltalk.

+0

Спасибо за ввод. Прошу прощения, у меня была неправильная терминология. Недавно я начал изучать ST и уже забыл разницу терминов. Насколько велика 'n', насколько велика слишком большая? Я думаю, если это 4 или 5, это выглядит уродливым. Но это субъективно. Конечно, я лучше понимаю философию языка и много читаю об этом. Я не обязательно «пытаюсь склонить его к своей воле», но ищет понимания. Для меня (недавнее обращение к ST) способность * chain * только селекторов, у которых нет аргументов, казалась мне непоследовательной. – lurker

+0

Я понимаю, что не всегда могу отправлять сообщения в том порядке, в котором я хочу. Я говорил о проблеме, в которой, в моем случае, я * хотел сделать это. Поэтому я не мог рассматривать его как 's1: s2: s3: ...' который заставляет порядок. Спасибо, что предоставили ссылку, я прочитаю ее. – lurker

+0

Не нужно извиняться, просто подумал, что я уточню, потому что я смутился, когда впервые прочитал вопрос. И, конечно, вы правы, что это субъективно. Я просто нахожу, что люди, приезжающие в Smalltalk с других языков, как правило, неохотно создают новые (небольшие) объекты и методы. Достаточно справедливо о порядке сообщений, спасибо за объяснение. Похоже, вы, вероятно, после шаблона. Престижность за попытку _get_ Smalltalk! :-) –

Смежные вопросы