Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Костя Ещенко, Вы писали:
КЕ>>И чем же не устраивает возможность гонять назад и т.п.?
VD>Несоотвествованием сути паттерна.
Неправда. Суть паттерана итератор — получить доступ к элементам коллекции не зная структуры или интерфейса самой коллекции.
Здравствуйте, vdimas, Вы писали:
V>Неправда. Суть паттерана итератор — получить доступ к элементам коллекции не зная структуры или интерфейса самой коллекции.
Не получить доступ, а переборать. Как по-твоему итератор переводится iterator?
Иначе указатели и массивы тоже будут итераторами.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, vdimas, Вы писали:
V>>Неправда. Суть паттерана итератор — получить доступ к элементам коллекции не зная структуры или интерфейса самой коллекции.
VD>Не получить доступ, а переборать. Как по-твоему итератор переводится iterator?
VD>Иначе указатели и массивы тоже будут итераторами.
ok, перебрать.
И где ограничение на способ или направление перебора?
В описании этого паттерна в GoF такие вещи не уточняются, да и не должны, ибо они не требуются для описания сути паттерна. Однако нигде и не говорится об ограничениях. С чего это тебе захотелось заняться ограничением имплементации паттернов — непонятно.
Ты же не делаешь, например, интерпретатор в том голом виде, как он представлен в паттернах GoF?
Здравствуйте, vdimas, Вы писали:
V>А паттерны — вещь хорошая, разумеется, но им стоило бы быть аккуратнее в именовании тех вещей, в которых не они были первыми. Итератор из GoF они могли бы назвать и подругому, дабы избежать обсуждаемого конфликта одноименных понятий.
Насколько мне известно итераторы появились несколько раньше итераторов STL. И выглядели они именно как паттерн итератор, описанный GoF. Вообще ребята из GoF не изобретали паттернов, они их только описали. Скорее Степанову следовало бы назвать "итераторы STL" как-нибудь по другому. В STL "итераторы" это скорее constrained pointer abstraction, несколько более общая и интересная концепция чем "паттерн итератор".
Вот вариант на D.
Сканирование последовательности выполняется единожды.
Не требует создания объектов P1, P2 и f —
условия и действо записываются inline.
Можно управлять ситуацией — end condition входит или нет
bool found;
foreach( element e; MyCont )
{
if( !found || P1(e) ) found = true; else continue;
if( P2(e) ) break; // open-range case
f(); // your code is here
}
Какой из паттернов естественнее (find_if или foreach) — дело вкуса.
То же самое можно написать и с помощью стандартного stl::iterator
Как правило в реальной жизни P1, P2 и f нетривиальны.
Поэтому компактность J>MyCont::iterator it1 = std::find_if(cont.begin(), cont.end(), P1); J>MyCont::iterator it2 = std::find_if(it1, cont.end(), P2);
записи пропадает напрочь.
Я лично предпочитаю вариант без find_if. Но это опять же
субъективно.
CS> bool found;
CS> foreach( element e; MyCont )
CS> {
CS> if( !found || P1(e) ) found = true; else continue;
CS> if( P2(e) ) break; // open-range case
CS> f(); // your code is here
CS> }
CS>Какой из паттернов естественнее (find_if или foreach) — дело вкуса...
В пользу STL-ного варианта могу сказать, что это явная запись намерений. Он читается с той же скоростью, что и описание задачи на natural language.
В твой вариант все-таки приходится вдумываться — зачем там found и в каких случаях выполнение все-таки дойдет до f().
То есть по изяществу и выразительности тут все-таки рулит STL
CS>>Какой из паттернов естественнее (find_if или foreach) — дело вкуса...
ЗХ>В пользу STL-ного варианта могу сказать, что это явная запись намерений. Он читается с той же скоростью, что и описание задачи на natural language. ЗХ>В твой вариант все-таки приходится вдумываться — зачем там found и в каких случаях выполнение все-таки дойдет до f().
ЗХ>То есть по изяществу и выразительности тут все-таки рулит STL
На самом D я бы для своего контейнера написал так:
Здравствуйте, VladD2, Вы писали:
MS>>Другое дело — сложившиеся традиции. VD>Точнее дурные традиции сложившиеся в некоторых кругах.
Года эдак с 1960-го примерно. И всё дурят старики.
MS>> Для простоты под понятием "список" подразумевается именно "linked list с последовательным доступом" и ничто другое. VD>Почему-то такое предположение больше делают С-шники. Я как-то не слышал, чтобы обычные люди или математики делали подобные предположения.
Nакая трактовка понятия "список" была уже в LISP, а это начало 60-х гг. Языка C, между прочим, тогда ещё и в проекте не было.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, jazzer, Вы писали: J>Например. Просто мне каким-то образом известно начало и конец подпоследовательности (в STL это итераторы, в .Net — пусть соответствующие гуру скажут), и я хочу с этой самой подпоследовательностью что-нть сделать. Например, развернуть ее.
Ключевой момент — "каким-то образом". Где ты возьмешь этот "конец подпоследовательности"? J>пример понятен: в C# все будет основываться на индексах в главной последовательности, и, соответственно, для итерации по подпоследовательности нужны эти два индекса и сама эта главная последовательность.
Нет. Я просто привел пример "какого-то образа" получения того самого итератора, спозиционированного хрен знает куда. Итератор "конца последовательности" в .Net не нужен. Какие еще есть полезные способы? Пример с индексами я привел. Приведи другие примеры — и ты убедишься, что есть способ выразить их в терминах .Net.
Не надо пытаться слепо переносить технические приемы из одной среды в другую. В каждом языке — свой способ решить некоторую задачу.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Такой подход либо требует контейнера с произвольным доступом, либо приводит к дополнительному проходу по элементам там, где в случае итераторов он не нужен.
Паша, не делай глупое лицо. Я тебе привел пример контейнера, который позволяет получать подпоследовательность с N до M. Что, в плюсах каким-то магическим образом удастся избавиться от лишнего прохода? Нет, не удастся. Ну и о чем тогда спор?
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, jazzer, Вы писали: J>>Например. Просто мне каким-то образом известно начало и конец подпоследовательности (в STL это итераторы, в .Net — пусть соответствующие гуру скажут), и я хочу с этой самой подпоследовательностью что-нть сделать. Например, развернуть ее. S>Ключевой момент — "каким-то образом". Где ты возьмешь этот "конец подпоследовательности"? J>>пример понятен: в C# все будет основываться на индексах в главной последовательности, и, соответственно, для итерации по подпоследовательности нужны эти два индекса и сама эта главная последовательность. S>Нет. Я просто привел пример "какого-то образа" получения того самого итератора, спозиционированного хрен знает куда. Итератор "конца последовательности" в .Net не нужен. Какие еще есть полезные способы? Пример с индексами я привел. Приведи другие примеры — и ты убедишься, что есть способ выразить их в терминах .Net. S>Не надо пытаться слепо переносить технические приемы из одной среды в другую. В каждом языке — свой способ решить некоторую задачу.
J>Все. Это полный код. Если не нашлось элементов, удовлетворяющих Р1 и Р2 — просто ничего не произойдет, так что тут даже никакой дополнительной защиты не нужно.
Прекрасный пример.
Итак, давайте представим себе, как будет решена эта задача на С#2.0. Влад уже привел ответ, правда, на другую задачу.
Итак, поехали:
/// Выводит ту часть последовательности input, которая не удовлетворяет критерию limit:public static IEnumerable<T> Limit(IEnumerable<T> input, Predicate<T> limit)
{
foreach(T t in input)
if (limit(t)) return;
else yield return t;
}
/// выводит элементы последовательности input начиная с того, который удовлетворяет start.public static IEnumerable<T> After(IEnumerable<T> input, Predicate<T> start)
{
bool found = false;
foreach(T t in input)
{
found |= start(t);
if(found)
yield return t;
}
}
/// Собственно, код задачи.public static ApplyWithinLimits(IEnumerable input, Action<T> action, Predicate<T> startAt, Predicate<T> stopAt)
{
foreach(T t in Limit(After(input, startAt), stopAt))
action(t);
}
Что мы видим? Да, появилось два "лишних" метода. Они не предусмотрены стандартной библиотекой. Однако, мы восполнили их отсутствие весьма простым и тривиальным способом. Если задачи, которые мы решаем, часто требуют подобных приемов, то эти методы осядут в библиотеке проекта. И объем необходимого кода будет не больше, чем для STL.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Sinclair,
> Итак, давайте представим себе, как будет решена эта задача на С#2.0. <...> >
> /// Выводит ту часть последовательности input, которая не удовлетворяет критерию limit:
> public static IEnumerable<T> Limit(IEnumerable<T> input, Predicate<T> limit)
> {
> foreach(T t in input)
> if (limit(t)) return;
> else yield return t;
> }
>
> /// выводит элементы последовательности input начиная с того, который удовлетворяет start.
> public static IEnumerable<T> After(IEnumerable<T> input, Predicate<T> start)
> {
> bool found = false;
> foreach(T t in input)
> {
> found |= start(t);
> if(found)
> yield return t;
> }
> }
> /// Собственно, код задачи.
> public static ApplyWithinLimits(IEnumerable input, Action<T> action, Predicate<T> startAt, Predicate<T> stopAt)
> {
> foreach(T t in Limit(After(input, startAt), stopAt))
> action(t);
> }
>
Спасибо! Два вопроса.
1) Такая связка Limit и After обеспечивает то, что элементы последовательности, идущие после stopAt, перебираться в итоге вообще не будут?
2) А если нам понадобится в Apply изменить порядок обхода найденной подпоследовательности, скажем, на обратный, какие из функций нужно будет переписать? Подозреваю, что все... В случае STL нужно будет только добавить пару вызовов для создания reverse_iterator, ничего из использованных алгоритмов (find_if, for_each) не переписывая.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>1) Такая связка Limit и After обеспечивает то, что элементы последовательности, идущие после stopAt, перебираться в итоге вообще не будут?
Нет, не будут. В комменте, ИМХО, ошибка, видимо должно быть как-то так:
>> /// Выводит элементы последовательности input до тех пор, пока соблюдается критерий limit:
>> public static IEnumerable<T> Limit(IEnumerable<T> input, Predicate<T> limit)
ПК>2) А если нам понадобится в Apply изменить порядок обхода найденной подпоследовательности, скажем, на обратный, какие из функций нужно будет переписать? Подозреваю, что все... В случае STL нужно будет только добавить пару вызовов для создания reverse_iterator, ничего из использованных алгоритмов (find_if, for_each) не переписывая.
В ApplyWithinLimits надо передавать уже IEnumerable, обходящий последовательность в обратном порядке. Менять же Limit и After не придётся.
Help will always be given at Hogwarts to those who ask for it.
_FRED_,
> ПК> если нам понадобится в Apply изменить порядок обхода найденной подпоследовательности, скажем, на обратный, какие из функций нужно будет переписать? Подозреваю, что все... В случае STL нужно будет только добавить пару вызовов для создания reverse_iterator, ничего из использованных алгоритмов (find_if, for_each) не переписывая. > > В ApplyWithinLimits надо передавать уже IEnumerable, обходящий последовательность в обратном порядке. Менять же Limit и After не придётся.
Нужно, чтоб начало и конец подпоследовательности искались в порядке прямого обхода, а элементы самой подпоследовательности уже обходились в обратном порядке. В предложенном же варианте и подпоследовательность будет выделяться в порядке обратного обхода.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Sinclair,
> ПК>Такой подход либо требует контейнера с произвольным доступом, либо приводит к дополнительному проходу по элементам там, где в случае итераторов он не нужен.
> <...> Я тебе привел пример контейнера, который позволяет получать подпоследовательность с N до M. Что, в плюсах каким-то магическим образом удастся избавиться от лишнего прохода?
В плюсах (точнее, не в плюсах, а если итератор представляет собой позицию) будут только необходимые проходы. Если вместо итераторов вводятся числа, обозначающие порядковый номер элемента, как это было в примере выше, то в общем случае проходов будет больше: первый, чтоб найти элемент, и потом еще по проходу каждый раз, когда данный элемент нужен еще раз, т.к. по индексу без произвольного доступа элемент можно получить только перечислением.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> ПК>Такой подход либо требует контейнера с произвольным доступом, либо приводит к дополнительному проходу по элементам там, где в случае итераторов он не нужен.
ПК>В плюсах (точнее, не в плюсах, а если итератор представляет собой позицию)
Т.е. это контейнер с произвольным доступом ПК>будут только необходимые проходы. Если вместо итераторов вводятся числа, обозначающие порядковый номер элемента, как это было в примере выше, то в общем случае проходов будет больше: первый, чтоб найти элемент, и потом еще по проходу каждый раз, когда данный элемент нужен еще раз, т.к. по индексу без произвольного доступа элемент можно получить только перечислением.
то есть дополнительный проход.
Можно еще раз объяснить, где "такой подход приводит к дополнительному проходу там, где он не нужен"?
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Павел Кузнецов, Вы писали: >> ПК> если нам понадобится в Apply изменить порядок обхода найденной подпоследовательности, скажем, на обратный, какие из функций нужно будет переписать? Подозреваю, что все... В случае STL нужно будет только добавить пару вызовов для создания reverse_iterator, ничего из использованных алгоритмов (find_if, for_each) не переписывая. >> В ApplyWithinLimits надо передавать уже IEnumerable, обходящий последовательность в обратном порядке. Менять же Limit и After не придётся. ПК>Нужно, чтоб начало и конец подпоследовательности искались в порядке прямого обхода, а элементы самой подпоследовательности уже обходились в обратном порядке. В предложенном же варианте и подпоследовательность будет выделяться в порядке обратного обхода.
Да, именно так и будет, я не совсем понял вопрос. Рискну предположить, что без потери "лености" итераторов в обратном порядке результат их работы не обойти
Help will always be given at Hogwarts to those who ask for it.