Здравствуйте, samius, Вы писали:
S>Здравствуйте, Sinclair, Вы писали:
S>>Это потому, что имеющаяся реализация yield return реализует стандартный IEnumerable<T>. Её можно было бы "починить", если бы результат GetEnumerator реализовывал бы ICloneable<IEnumerator<T>>. S>>А окончательно её можно было бы починить, если бы в IEnumerator<T> MoveNext возвращал не void, а IEnumerator<T>. S>>Тогда бы за хранение состояния отвечал бы клиентский код, вместо $iterator.MoveNext было бы $iterator=$iterator.MoveNext. S>Задача перебора будет решена, но это уже не паттерн Iterator
Это собственно будет намного ближе к монаде State чем к паттерну Iterator. И это очень и очень далекие вещи, хоть и могут решать схожие задачи.
Re[22]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали:
S>>Тогда бы за хранение состояния отвечал бы клиентский код, вместо $iterator.MoveNext было бы $iterator=$iterator.MoveNext. S>Задача перебора будет решена, но это уже не паттерн Iterator
В узком смысле — да. В широком смысле — паттерн по-прежнему имеет смысл.
S>>Классика жанра — результатом вызова модифицирующих методов является новый объект. S>>См. напр. System.String. S>Но при этом исходный объект свое наблюдаемое состояние не меняет. Классика жанра основана именно на этом.
В принципе, да. С другой стороны, философия классики в том, что объект имеет право реагировать на сообщения с учётом своего состояния, и в том что другого способа узнать состояние объекта нет.
Вопрос, является ли неизменяемое состояние вообще состоянием или нет — весьма философский. Ну, то есть мы могли бы с тем же успехом считать объект вместе со встроенным состоянием объектом отдельного "класса" — ведь именно класс диктует поведение объекта. Итератор, показывающий на последний элемент списка, всегда вернёт null из MoveNext.
Есть ещё один щекотливый момент: что считать идентичностью в этом случае.
Два объекта в одинаковом состоянии неразличимы — нет способа "изменить" только один из них. Считать ли два состояния одного и того же объекта идентичными или нет?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>>Тогда бы за хранение состояния отвечал бы клиентский код, вместо $iterator.MoveNext было бы $iterator=$iterator.MoveNext. S>>Задача перебора будет решена, но это уже не паттерн Iterator S>В узком смысле — да. В широком смысле — паттерн по-прежнему имеет смысл.
Поспешил я. Иммутабельности ведь нет (см выделенное), хоть перебрать иммутабельно все-таки можно через рекурсию, либо свертку.
И все-таки. Итератором в широком смысле этот подход назвать можно. И даже нужно, наряду с другими подходами, перечисленными в The Essence of the Iterator Pattern.
Но итератором по GoF это не является, а именно этот конкретный паттерн я подразумевал изначально.
S>>>Классика жанра — результатом вызова модифицирующих методов является новый объект. S>>>См. напр. System.String. S>>Но при этом исходный объект свое наблюдаемое состояние не меняет. Классика жанра основана именно на этом. S>В принципе, да. С другой стороны, философия классики в том, что объект имеет право реагировать на сообщения с учётом своего состояния, и в том что другого способа узнать состояние объекта нет.
Согласен, но с уточнением что не своего, а вообще любого состояния. Неизменяемым считается тот объект, который реагирует идентично на все сообщения на протяжении всего своего существования, не зависимо от side-effectoв, фаз луны, и прочего вроде наличия слушателя на другом конце TCP.
S>Вопрос, является ли неизменяемое состояние вообще состоянием или нет — весьма философский. Ну, то есть мы могли бы с тем же успехом считать объект вместе со встроенным состоянием объектом отдельного "класса" — ведь именно класс диктует поведение объекта. Итератор, показывающий на последний элемент списка, всегда вернёт null из MoveNext.
Полагаю что речь исключительно об итераторе, который возвращает новый итератор при MoveNext, явно ничего не изменяя.
Тогда тут два аспекта:
1) — что вернет итератор, показывающий на последний элемент списка после того как к списку добавят элемент?
Если что-то отличное от null — исключение, или "очередной итератор", то говорить об иммутабельности такого итератора нельзя однозначно.
2) — я уверен в том что в языках с номинальной системой типов иммутабельными объектами считаются объекты тех типов, чьи экземпляры все иммутабельны. Т.е. не должно быть такого что new A(immutable: true) является иммутабельным, а new A() не является. Значит итератор не будет иммутабельным, если он имеет техническую возможность ссылаться на мутабельный контейнер.
S>Есть ещё один щекотливый момент: что считать идентичностью в этом случае. S>Два объекта в одинаковом состоянии неразличимы — нет способа "изменить" только один из них. Считать ли два состояния одного и того же объекта идентичными или нет?
Состояния — да. Будут ли идентичны сами объекты — вопрос интереснее.
Если ссылаться на руководство для implementers Object.Equals, то нарушается пункт
Successive calls to x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.
Изменение по крайней мере одного объекта можно считать side effect-ом, потому при сравнении его с третьим объектом, который не изменил свое состояние вместе с первыми двумя, нарушится условие.
Можно усугубить: пусть нет способа изменить лишь один объект из всех (а не только из двух). Типичный паттерн Monostate. Считать ли все возможные состояния идентичными? Допускаю.
А причем тут вообще идентичность?
Re[24]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали: S>1) — что вернет итератор, показывающий на последний элемент списка после того как к списку добавят элемент? S>Если что-то отличное от null — исключение, или "очередной итератор", то говорить об иммутабельности такого итератора нельзя однозначно.
S>2) — я уверен в том что в языках с номинальной системой типов иммутабельными объектами считаются объекты тех типов, чьи экземпляры все иммутабельны. Т.е. не должно быть такого что new A(immutable: true) является иммутабельным, а new A() не является. Значит итератор не будет иммутабельным, если он имеет техническую возможность ссылаться на мутабельный контейнер.
Конечно же иммутабельность итератора подразумевает и иммутабельность итерируемого. В связи с этим п.1 не проблема.
S>Состояния — да. Будут ли идентичны сами объекты — вопрос интереснее.
Вот тут как раз непонятно, как отделить "состояния" от "самих объектов".
То есть вот у нас есть
S>Successive calls to x.Equals(y) return the same value as long as the objects referenced by x and y are not modified. S>
Непонятно, что имеется в виду. Все объекты — иммутабельны; поэтому никаких нарушений нет.
S>А причем тут вообще идентичность?
Ну так это же основа ООП. Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>Состояния — да. Будут ли идентичны сами объекты — вопрос интереснее. S>Вот тут как раз непонятно, как отделить "состояния" от "самих объектов".
Еще раз перечитал вопрос — признаюсь, я его походу не понял. И сейчас нет ясности.
S>То есть вот у нас есть S>
S>Кто из них считается эквивалентным?
Эквивалентным по какому признаку?
Ссылочно — наверняка нет (не исключено обратное)
Эквивалентно по набору реакций на сообщения — можно определить такую эквивалентность, но боюсь, ее придется определять рекурсивно через итераторы, возвращаемые Next()-ом в том числе.
Эквивалентно по контейнеру и позиции в нем — наверное iterator1 и iterator2 будут эквивалентны.
Я не очень понимаю, к чему вопрос.
S>>Если ссылаться на руководство для implementers Object.Equals, то нарушается пункт S>>
S>>Successive calls to x.Equals(y) return the same value as long as the objects referenced by x and y are not modified. S>>S>Непонятно, что имеется в виду. Все объекты — иммутабельны; поэтому никаких нарушений нет.
"нет способа изменить только один из них" — предполагает способ изменить сразу оба. Разве нет? Я исходил из этого.
S>>А причем тут вообще идентичность? S>Ну так это же основа ООП.
Сомневаюсь
Один из основных инструментов ООП — возможно. Но не основа.
S>Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что.
Откуда это следует?
Re[26]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали: S>Эквивалентным по какому признаку? S>Я не очень понимаю, к чему вопрос.
Вы понимаете, что значит identity в ООП? Это гарантированный способ идентифицировать конкретный объект.
В обычной архитектуре достигается благодаря понятию ссылки на объект. Для ссылок определена такая операция сравнения, которая даёт истину в том случае, если ссылки указывают на один и тот же объект, и ложь в противном случае.
Именно благодаря идентичности вообще есть возможность послать сообщение заданному объекту.
Кроме того, очень важным моментом является то, что идентичность всегда сохраняется. То есть если мы получили ссылку r1 на объект о1, а через произвольное "время" мы получили ссылку r2 на тот же объект, то r1 == r2. Независимо от того, изменилось ли состояние o1 или нет.
Если у нас нет такого свойства, то это однозначно не ООП.
S>Сомневаюсь S>Один из основных инструментов ООП — возможно. Но не основа. S>>Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что. S>Откуда это следует?
Из определения. В ООП программа представляется набором объектов, обладающих
— идентичностью, т.е. возможностью послать сообщение конкретному объекту
— поведением, т.е. возможностью реагировать на сообщения некоторым образом
— состоянием, т.е. возможностью варьировать своё поведение в зависимости от истории принятых сообщений.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[27]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали: S>>Эквивалентным по какому признаку? S>>Я не очень понимаю, к чему вопрос. S>Вы понимаете, что значит identity в ООП? Это гарантированный способ идентифицировать конкретный объект.
Я понимаю что значит идентичность, но не понимаю, к чему речь о ней.
S>Кроме того, очень важным моментом является то, что идентичность всегда сохраняется. То есть если мы получили ссылку r1 на объект о1, а через произвольное "время" мы получили ссылку r2 на тот же объект, то r1 == r2. Независимо от того, изменилось ли состояние o1 или нет.
Речь о ссылочной идентичности? Верно?
S>Если у нас нет такого свойства, то это однозначно не ООП.
Отлично. Вернемся к этому
с итераторами, возвращающими новый экземпляр итератора на MoveNext в точности то же самое, пока итераторы возвращаются не по значению. А смысла использовать структурную эквивалентность для итераторов я не вижу.
вернемся к
Два объекта в одинаковом состоянии неразличимы — нет способа "изменить" только один из них. Считать ли два состояния одного и того же объекта идентичными или нет?
Я до сих пор не понимаю ни суть вопроса, ни к чему он задан. И о какой идентичности все же идет речь? О ссылочной или структурной?
S>>Сомневаюсь S>>Один из основных инструментов ООП — возможно. Но не основа. S>>>Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что. S>>Откуда это следует? S>Из определения. В ООП программа представляется набором объектов, обладающих S>- идентичностью, т.е. возможностью послать сообщение конкретному объекту S>- поведением, т.е. возможностью реагировать на сообщения некоторым образом S>- состоянием, т.е. возможностью варьировать своё поведение в зависимости от истории принятых сообщений.
Понятно. Ссылочная идентичность никуда не делась. Потому не понимаю, к чему было следующее:
Ну так это же основа ООП. Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что.
Re[28]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали:
S>Речь о ссылочной идентичности? Верно?
Речь об идентичности. Которая в случае традиционной реализации соответствует ссылочной эквивалентности.
S>
S>Какие из них идентичны? Если никто из них, то это однозначно не ООП?
1. Не очень понял, что такое "штатные итераторы дотнета" в применении к данному примеру. Штатные итераторы не умеют так, как написано в строчке 2.
2. Если iterator1 не эквивалентен iterator2, то это нифига не ООП — мы не можем отличить разные состояния одного и того же объекта от разных объектов.
3. Если iterator1 эквивалентен iterator3, то это нифига не ООП — различные объекты невозможно отличить друг от друга.
S>Однако, если речь о ссылочной (shallow) идентичности, то она присутствует: S>
Данный пример никак не раскрывает вопроса наличия либо отсутствия ООП. Он будет работать с любыми ATD.
S>с итераторами, возвращающими новый экземпляр итератора на MoveNext в точности то же самое, пока итераторы возвращаются не по значению.
Не понял вот этой фразы. Можно мне её как-то развернуть? Будет ли способ установить идентичность iterator2 и iterator1?
S>Я до сих пор не понимаю ни суть вопроса, ни к чему он задан. И о какой идентичности все же идет речь? О ссылочной или структурной?
Вы, похоже, считаете термины "идентичность" и "эквивалентность" взаимозаменяемыми.
На самом деле они практически противоположны — прочитайте определение.
S>Понятно. Ссылочная идентичность никуда не делась.
Термина "ссылочная идентичность" не существует. S>
S>Ну так это же основа ООП. Если у нас нет идентичности (т.е. identity, которая, имхо, на самом деле идентифицируемость) то это вообще не ООП а непонятно что.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[29]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>Речь о ссылочной идентичности? Верно? S>Речь об идентичности. Которая в случае традиционной реализации соответствует ссылочной эквивалентности.
Окей. Но я решительно не понимаю, куда пропадает ссылочная эквивалентность в обсуждаемых примерах.
S>>Какие из них идентичны? Если никто из них, то это однозначно не ООП? S>1. Не очень понял, что такое "штатные итераторы дотнета" в применении к данному примеру. Штатные итераторы не умеют так, как написано в строчке 2.
Да, не умеют. Можно не рассматривать 2-ую строчку применительно к штатным итераторам. Ссылочная эквивалентность iterator1 и iterator3 сохраняется и с нештатными итераторами. Т.е. может эквивалентны ссылочно, а может и нет. Обычно нет.
S>2. Если iterator1 не эквивалентен iterator2, то это нифига не ООП — мы не можем отличить разные состояния одного и того же объекта от разных объектов.
Вообще говоря не понимаю, почему iteratro1 должен быть эквивалентен итератору2. А так же не понимаю, о каких различных состояниях одного и того же объекта речь в контексте иммутабельных объектов... Во всяком случае внешнего проявления изменения состояний быть не должно, а значит и на идентичность они не могут повлиять по определению иммутабельного объекта.
S>3. Если iterator1 эквивалентен iterator3, то это нифига не ООП — различные объекты невозможно отличить друг от друга.
Откуда следует что они различные?
И какие предполагаются отличия иммутабельных итераторов от штатных в этом аспекте? Если реализация возвращает каждый раз отличные объекты, почему они вдруг станут эквивалентными (ссылочно я полагаю)?
S>Данный пример никак не раскрывает вопроса наличия либо отсутствия ООП. Он будет работать с любыми ATD.
ок, опустим его
S>>с итераторами, возвращающими новый экземпляр итератора на MoveNext в точности то же самое, пока итераторы возвращаются не по значению. S>Не понял вот этой фразы. Можно мне её как-то развернуть? Будет ли способ установить идентичность iterator2 и iterator1?
Вот это надо узнать у автора идеи, или у того, кто ее здесь представил. Честно говоря, кроме $iterator=$iterator.MoveNext я о ней ничего не знаю. Могу предположить что в конце последовательности MoveNext будет возвращать this.
Если речь о традиционной реализации, то iterator1 и iterator2 могут быть ссылочно эквивалентны. А могут и не быть. Что это дает в вопросе наличия либо отсутствия ООП?
И что подразумевается под установкой идентичности iterator2 и iterator1? Убедиться что это разные объекты? Или что они одинаковые?
А сказать я хотел лишь то, что не вижу каких-то принципиальных отличий штатных итераторов от итераторов, возвращающих итератор на MoveNext в плане идентичности, кроме того факта, что последние возвращают новый итератор (возможно и нет в случае конца последовательности, т.к. я не знаю, что именно служит признаком конца последовательности, может и null).
S>>Я до сих пор не понимаю ни суть вопроса, ни к чему он задан. И о какой идентичности все же идет речь? О ссылочной или структурной? S>Вы, похоже, считаете термины "идентичность" и "эквивалентность" взаимозаменяемыми. S>На самом деле они практически противоположны — прочитайте определение.
Прочитал. Теперь я не понимаю следующее: Если в традиционной реализации идентичность соответствует ссылочной эквивалентности, то куда пропадает ссылочная эквивалентность при изменении модели итератора? Тот же вопрос вначале поста.
И главное я не понимаю того, как изменение модели итератора влияет на наличие ООП, притом что реализация традиционная, ссылочная эквивалентность а значит и идентичность присутствуют. Может я еще не понимаю о традиционной реализации чего именно идет речь?
Re[30]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали:
S>Да, не умеют. Можно не рассматривать 2-ую строчку применительно к штатным итераторам. Ссылочная эквивалентность iterator1 и iterator3 сохраняется и с нештатными итераторами. Т.е. может эквивалентны ссылочно, а может и нет. Обычно нет.
S>>2. Если iterator1 не эквивалентен iterator2, то это нифига не ООП — мы не можем отличить разные состояния одного и того же объекта от разных объектов. S>Вообще говоря не понимаю, почему iteratro1 должен быть эквивалентен итератору2.
Потому что в "обычном" ООП iterator2 — это тот же самый итератор1 после обработки сообщения moveNext. Переход к immutable, получается, теряет это свойство. Мы не можем взять, к примеру, внешний словарь, сохранить в нём некое значение для нашего итератора, и через время T получить это значение, скормив ему iterator2. S>А так же не понимаю, о каких различных состояниях одного и того же объекта речь в контексте иммутабельных объектов... Во всяком случае внешнего проявления изменения состояний быть не должно, а значит и на идентичность они не могут повлиять по определению иммутабельного объекта.
Ну как это не понимаете. Если мы хотим эмулировать ООП, то вместо монолитного объекта, который меняет своё состояние "на месте", мы имеем цепочку состояний. Что мы будем иметь вместо identity?
S>Откуда следует что они различные?
Ну, они могут быть и одинаковыми. Вопрос, собственно, в том — могут ли они быть различными?
S>И какие предполагаются отличия иммутабельных итераторов от штатных в этом аспекте? Если реализация возвращает каждый раз отличные объекты, почему они вдруг станут эквивалентными (ссылочно я полагаю)?
Я говорю не про реализацию. Предположим, она корректно реализует все требования. Какие именно требования вы предъявите, чтобы модель оставалась ООПшной?
S>>Не понял вот этой фразы. Можно мне её как-то развернуть? Будет ли способ установить идентичность iterator2 и iterator1? S>Вот это надо узнать у автора идеи, или у того, кто ее здесь представил. Честно говоря, кроме $iterator=$iterator.MoveNext я о ней ничего не знаю. Могу предположить что в конце последовательности MoveNext будет возвращать this.
Если this — иммутабелен, то смысла его возвращать нету. MoveNext никуда не сдвинется.
S>Если речь о традиционной реализации, то iterator1 и iterator2 могут быть ссылочно эквивалентны. А могут и не быть. Что это дает в вопросе наличия либо отсутствия ООП?
Это даёт наличие либо отсутствие ООП.
S>И что подразумевается под установкой идентичности iterator2 и iterator1? Убедиться что это разные объекты? Или что они одинаковые?
Убедиться, что они одинаковые, отличающиеся от всех других итераторов.
S>Прочитал. Теперь я не понимаю следующее: Если в традиционной реализации идентичность соответствует ссылочной эквивалентности, то куда пропадает ссылочная эквивалентность при изменении модели итератора? Тот же вопрос вначале поста.
Как куда? Раньше мы могли сохранять ссылку на итератор, меняя его состояние. Теперь мы вынуждены всё время её обновлять, следя за "состоянием". Вот вам и пропадание ссылочной эквивалентности. Я же привёл пример с iterator1/iterator2. В традиционной реализации мы можем написать вот так:
var iterator2 = iterator1;
iterator2.MoveNext();
Console.WriteLine(iterator2 == iterator1); // true
S>И главное я не понимаю того, как изменение модели итератора влияет на наличие ООП, притом что реализация традиционная, ссылочная эквивалентность а значит и идентичность присутствуют. Может я еще не понимаю о традиционной реализации чего именно идет речь?
Традиционная реализация — мутабельная.
Попытка реализовать итератор иммутабельным, судя по всему, не соответствует математике ООП.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[31]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>>А так же не понимаю, о каких различных состояниях одного и того же объекта речь в контексте иммутабельных объектов... Во всяком случае внешнего проявления изменения состояний быть не должно, а значит и на идентичность они не могут повлиять по определению иммутабельного объекта. S>Ну как это не понимаете. Если мы хотим эмулировать ООП, то вместо монолитного объекта, который меняет своё состояние "на месте", мы имеем цепочку состояний. Что мы будем иметь вместо identity?
Эээ... Собственно, конкретное состояние в какой-то момент времени. Какие проблемы-то?
Sapienti sat!
Re[32]: Почему объектно-ориентированное программирование про
Здравствуйте, Cyberax, Вы писали:
C>Эээ... Собственно, конкретное состояние в какой-то момент времени. Какие проблемы-то?
Проблемы лично у меня с тем, что identity получается утеряна. В классическом ООП можно абстрагироваться от состояния объекта, и отличать его от всех других.
К примеру, можно иметь некий dictionary, в котором лежат строки, индексированные thread.
В любой момент можно пойти в этот dictionary, имея ссылку на текущее состояние потока, и получить нужную строку.
В immutable реализации это невозможно: строку складывали со "старым" потоком, ищем с "новым".
Придётся вносить какой-нибудь threadID, который будет сохраняться при смене состояния потока.
А это и есть "ручная идентичность" в противовес "встроенной".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
C>>Эээ... Собственно, конкретное состояние в какой-то момент времени. Какие проблемы-то? S>Проблемы лично у меня с тем, что identity получается утеряна. В классическом ООП можно абстрагироваться от состояния объекта, и отличать его от всех других.
Почему?? Скажем, два разных объекта в функциональщине будут двумя разными объектами.
S>К примеру, можно иметь некий dictionary, в котором лежат строки, индексированные thread. S>В любой момент можно пойти в этот dictionary, имея ссылку на текущее состояние потока, и получить нужную строку.
А где здесь identity?
S>В immutable реализации это невозможно: строку складывали со "старым" потоком, ищем с "новым". S>Придётся вносить какой-нибудь threadID, который будет сохраняться при смене состояния потока. S>А это и есть "ручная идентичность" в противовес "встроенной".
Нет. Это пример однозначно не на идентичность, а на ссылочную прозрачность.
В случае с функциональностью ты ОБЯЗАН передать состояние всё состояние, которое используется. В императивном подходе ты можешь использовать глобальные контексты.
Sapienti sat!
Re[31]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>Вообще говоря не понимаю, почему iteratro1 должен быть эквивалентен итератору2. S>Потому что в "обычном" ООП iterator2 — это тот же самый итератор1 после обработки сообщения moveNext. Переход к immutable, получается, теряет это свойство.
Естественно. S>Мы не можем взять, к примеру, внешний словарь, сохранить в нём некое значение для нашего итератора, и через время T получить это значение, скормив ему iterator2.
Это верно. Но причем здесь ООП? Iterator2 это не тот же итератор Iterator1. Изменился способ итерирования по коллекции. Один итератор — одна позиция последовательности. Все равно что складывать в словарь позицию в массиве int *iter1, а потом после iter1++ пытаться что-то найти в словаре.
S>>А так же не понимаю, о каких различных состояниях одного и того же объекта речь в контексте иммутабельных объектов... Во всяком случае внешнего проявления изменения состояний быть не должно, а значит и на идентичность они не могут повлиять по определению иммутабельного объекта. S>Ну как это не понимаете. Если мы хотим эмулировать ООП, то вместо монолитного объекта, который меняет своё состояние "на месте", мы имеем цепочку состояний. Что мы будем иметь вместо identity?
Ничего не надо делать вместо. Итератор это не один и тот же объект и все тут.
Но что-то мне кажется что итератор это сложная тема для нахождения взаимопонимания в вопросе наличия ООП. Предлагаю переключиться на аналогичную ситуацию с String/StringBuilder и посмотреть на операции
sb.Append("foo");
s += "foo";
Для меня здесь нет различий между в аспекте наличия ООП. Отличны только способы взаимодействия с объектами. Один получая сообщение меняет свое состояние, второй — возвращает новое значение.
S>>И какие предполагаются отличия иммутабельных итераторов от штатных в этом аспекте? Если реализация возвращает каждый раз отличные объекты, почему они вдруг станут эквивалентными (ссылочно я полагаю)? S>Я говорю не про реализацию. Предположим, она корректно реализует все требования. Какие именно требования вы предъявите, чтобы модель оставалась ООПшной?
Она для меня ООП-шная насквозь, потому как я не считаю цепочку итераторов одним и тем же объектом, либо эмуляцией одного и того же объекта.
S>>Вот это надо узнать у автора идеи, или у того, кто ее здесь представил. Честно говоря, кроме $iterator=$iterator.MoveNext я о ней ничего не знаю. Могу предположить что в конце последовательности MoveNext будет возвращать this. S>Если this — иммутабелен, то смысла его возвращать нету. MoveNext никуда не сдвинется.
Ну почему же? Для конца коллекции вполне можно возвращать this что бы клиент сравнивая ссылки с предыдущим итератором убедился что сдвига не произошло. Я не говорю что так должно быть, это просто один из предпологаемых сценариев.
S>>Если речь о традиционной реализации, то iterator1 и iterator2 могут быть ссылочно эквивалентны. А могут и не быть. Что это дает в вопросе наличия либо отсутствия ООП? S>Это даёт наличие либо отсутствие ООП.
Честно говоря, походу меня перемкнуло когда я отвечал на предыдущий пост. В случае традиционной реализации iterator2 не может быть получен как результат MoveNext. Может я хотел что-то другое сказать/спросить, уже не помню.
S>>И что подразумевается под установкой идентичности iterator2 и iterator1? Убедиться что это разные объекты? Или что они одинаковые? S>Убедиться, что они одинаковые, отличающиеся от всех других итераторов.
2 и 1 одинаковые? Может и можно убедиться что они одинаковые в случае если на конце коллекции MoveNext возвращает this. Но в общем случае они не будут одинаковыми и будут отличаться от всех других (тем что ссылки на них не будут равны).
S>>Если в традиционной реализации идентичность соответствует ссылочной эквивалентности, то куда пропадает ссылочная эквивалентность при изменении модели итератора? Тот же вопрос вначале поста. S>Как куда? Раньше мы могли сохранять ссылку на итератор, меняя его состояние. Теперь мы вынуждены всё время её обновлять, следя за "состоянием". Вот вам и пропадание ссылочной эквивалентности. Я же привёл пример с iterator1/iterator2. В традиционной реализации мы можем написать вот так: S>
Да, можем. А в иммутабельной не можем на том основании что итератор вернется другой. Но ссылочная эквивалентность осталась:
var iterator2 = iterator1;
var iterator3 = iterator2.MoveNext();
Console.WriteLine(iterator2 == iterator1); // true
S>>И главное я не понимаю того, как изменение модели итератора влияет на наличие ООП, притом что реализация традиционная, ссылочная эквивалентность а значит и идентичность присутствуют. Может я еще не понимаю о традиционной реализации чего именно идет речь? S>Традиционная реализация — мутабельная. А, речь об реализации итератора. S>Попытка реализовать итератор иммутабельным, судя по всему, не соответствует математике ООП.
Я считаю что математика ООП не должна ожидать ссылочной эквивалентности от _разных_ объектов.
Re[34]: Почему объектно-ориентированное программирование про
Здравствуйте, Cyberax, Вы писали:
C>Здравствуйте, Sinclair, Вы писали:
C>>>Эээ... Собственно, конкретное состояние в какой-то момент времени. Какие проблемы-то? S>>Проблемы лично у меня с тем, что identity получается утеряна. В классическом ООП можно абстрагироваться от состояния объекта, и отличать его от всех других. C>Почему?? Скажем, два разных объекта в функциональщине будут двумя разными объектами.
Тут возникает философский вопрос — что значит "разные" объекты?
И сложность не только в том, чтобы различать разные объекты, но и чтобы уметь понять, что две ссылки показывают на один и тот же объект.
S>>К примеру, можно иметь некий dictionary, в котором лежат строки, индексированные thread. S>>В любой момент можно пойти в этот dictionary, имея ссылку на текущее состояние потока, и получить нужную строку. C>А где здесь identity?
Везде. Identity в данном случае — это способ отличить "этот" объект от всех других объектов.
Возможность обратиться в dictionary напрямую связана с сохранением identity. Операции над объектами в ООП сохраняют идентичность. В ФП — не сохраняют.
C>Нет. Это пример однозначно не на идентичность, а на ссылочную прозрачность. Referential transparency приводится в вики как антипод identity. В связи с этим, имхо, трудно придумать пример на одно так, чтобы он не был и примером на другое
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[32]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали:
S>Это верно. Но причем здесь ООП? Iterator2 это не тот же итератор Iterator1. Изменился способ итерирования по коллекции. Один итератор — одна позиция последовательности. Все равно что складывать в словарь позицию в массиве int *iter1, а потом после iter1++ пытаться что-то найти в словаре.
Очень хорошо. Я надеюсь, вы понимаете, что (int *) — это не ООП?
Итератор, определённый таким образом, ведёт себя не как объект, а как value-type.
S>Но что-то мне кажется что итератор это сложная тема для нахождения взаимопонимания в вопросе наличия ООП. Предлагаю переключиться на аналогичную ситуацию с String/StringBuilder и посмотреть на операции S>
S>sb.Append("foo");
S>s += "foo";
S>
S>Для меня здесь нет различий между в аспекте наличия ООП. Отличны только способы взаимодействия с объектами. Один получая сообщение меняет свое состояние, второй — возвращает новое значение.
Как бы вам так объяснить. Вы имеете полное право игнорировать общепринятые определения ООП, подразумевая под ним что-то своё. Но, во-первых, хотелось бы тогда увидеть ваше определение — каким критериям должна удовлетворять архитектура, чтобы считаться объектной или объектно-ориентированной? А во-вторых, не очень понятно желание отказаться от общепринятых терминов.
S>>Если this — иммутабелен, то смысла его возвращать нету. MoveNext никуда не сдвинется. S>Ну почему же? Для конца коллекции вполне можно возвращать this что бы клиент сравнивая ссылки с предыдущим итератором убедился что сдвига не произошло. Я не говорю что так должно быть, это просто один из предпологаемых сценариев.
Это, конечно, интересно. А в другие места коллекций итераторы у вас указывать могут? Зачем тогда фокусироваться на одном частном случае?
S>>Убедиться, что они одинаковые, отличающиеся от всех других итераторов. S>2 и 1 одинаковые? Может и можно убедиться что они одинаковые в случае если на конце коллекции MoveNext возвращает this. Но в общем случае они не будут одинаковыми и будут отличаться от всех других (тем что ссылки на них не будут равны).
В случае ООП итератор это объект. Объект в ООП всегда обладает идентичностью. Это означает, что есть способ установить эквивалентность iterator1 до MoveNext и его же после MoveNext.
S>Да, можем. А в иммутабельной не можем на том основании что итератор вернется другой. Но ссылочная эквивалентность осталась: S>
Эта эквивалентность не является ссылочной. Если мы поменяем семантику операций присваивания и сравнения на почленное копирование/сравнение, то поведение этого фрагмента программы не изменится.
S>Я считаю что математика ООП не должна ожидать ссылочной эквивалентности от _разных_ объектов.
Математика ООП ожидает наличия identity у объекта. Ссылочная эквивалентность — это способ реализации identity в традиционной реализации ООП — там, где объекты живут в "памяти", и можно идентифицировать объект по его "положению" в этой памяти.
В менее традиционных реализациях ООП, где, скажем, нет способа манипулировать "адресом" объекта, применяют OID — Object Identifier.
По итогам дискуссии получается, что у immutable "объектов" identity нет, то есть это не объекты с точки зрения ООП.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>Очень хорошо. Я надеюсь, вы понимаете, что (int *) — это не ООП?
(int *) — это не ООП S>Итератор, определённый таким образом, ведёт себя не как объект, а как value-type.
однако я не понимаю почему нельзя считать ООП $iterator = $iterator.MoveNext(). Куда делась идентичность объекта после вызова MoveNext()?
S>>
S>>sb.Append("foo");
S>>s += "foo";
S>>
S>>Для меня здесь нет различий между в аспекте наличия ООП. Отличны только способы взаимодействия с объектами. Один получая сообщение меняет свое состояние, второй — возвращает новое значение. S>Как бы вам так объяснить. Вы имеете полное право игнорировать общепринятые определения ООП, подразумевая под ним что-то своё. Но, во-первых, хотелось бы тогда увидеть ваше определение — каким критериям должна удовлетворять архитектура, чтобы считаться объектной или объектно-ориентированной? А во-вторых, не очень понятно желание отказаться от общепринятых терминов.
Что бы убедить меня в том что я от чего-то хочу отказаться, нужно показать как нарушается идентичность иммутабельного объекта после операций над ним. Например на строке. Что она такого теряет после += "foo"?
Или может строка это не объект? Тогда что отличает объект от необъекта? Ниужели наличие изменяемого состояния?
S>Это, конечно, интересно. А в другие места коллекций итераторы у вас указывать могут? Зачем тогда фокусироваться на одном частном случае?
Я не хотел на этом фокусироваться, просто ответил о том что iterator2 может быть идентичен iterator1.
S>В случае ООП итератор это объект. Объект в ООП всегда обладает идентичностью. Это означает, что есть способ установить эквивалентность iterator1 до MoveNext и его же после MoveNext.
То же самое и с иммутабельными итераторами. После MoveNext ничего с итератором не случается. Он остается самим собой и эквивалентен себе до MoveNext ссылочно и даже структурно (в контрасте с традиционным итератором).
S>>
S>Эта эквивалентность не является ссылочной. Если мы поменяем семантику операций присваивания и сравнения на почленное копирование/сравнение, то поведение этого фрагмента программы не изменится.
И я не вижу в этом проблему. Если объект от необъекта отличает необходимость изменять члены после каждой операции, то это плохой критерий.
S>Математика ООП ожидает наличия identity у объекта. Ссылочная эквивалентность — это способ реализации identity в традиционной реализации ООП — там, где объекты живут в "памяти", и можно идентифицировать объект по его "положению" в этой памяти.
Предлагаю оставаться в рамках традиционной реализации ООП, там где объект можно идентифицировать по его "положению".
S>По итогам дискуссии получается, что у immutable "объектов" identity нет, то есть это не объекты с точки зрения ООП.
Можно все-таки в коде увидеть признак отсутствия identity у immutable "объектов"? Примеры выше как-то это не показывают. В частности сравнение традиционных и иммутабельных итераторов (с вариациями строки с MoveNext) ведут себя одинаково если не копировать и не сравнивать их почленно.
Re[35]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>>>Проблемы лично у меня с тем, что identity получается утеряна. В классическом ООП можно абстрагироваться от состояния объекта, и отличать его от всех других. C>>Почему?? Скажем, два разных объекта в функциональщине будут двумя разными объектами. S>Тут возникает философский вопрос — что значит "разные" объекты? S>И сложность не только в том, чтобы различать разные объекты, но и чтобы уметь понять, что две ссылки показывают на один и тот же объект.
Собственно, это вопрос совсем к императивности и функциональности не относятся ровно никак.
S>>>В любой момент можно пойти в этот dictionary, имея ссылку на текущее состояние потока, и получить нужную строку. C>>А где здесь identity? S>Везде. Identity в данном случае — это способ отличить "этот" объект от всех других объектов.
Так и что? В функциональщине просто мутаций нет, всё остальное такое же. Точно так же, нужно уметь отличать один объект от другого.
S>Возможность обратиться в dictionary напрямую связана с сохранением identity. Операции над объектами в ООП сохраняют идентичность. В ФП — не сохраняют.
Сохраняют. Если мне передадут DictionaryA и DictionaryB — они могут быть разными. Если бы у них не было идентичности, то их можно было бы заменять один на другой, что очевидно не так.
Sapienti sat!
Re[22]: Почему объектно-ориентированное программирование про
Здравствуйте, samius, Вы писали:
S>>Это потому, что имеющаяся реализация yield return реализует стандартный IEnumerable<T>. Её можно было бы "починить", если бы результат GetEnumerator реализовывал бы ICloneable<IEnumerator<T>>. S>>А окончательно её можно было бы починить, если бы в IEnumerator<T> MoveNext возвращал не void, а IEnumerator<T>. S>>Тогда бы за хранение состояния отвечал бы клиентский код, вместо $iterator.MoveNext было бы $iterator=$iterator.MoveNext. S>Задача перебора будет решена, но это уже не паттерн Iterator
Итератор может быть "внешнием" и "внутренним", это по ГоФ. Если внутренним, то соответственно сколько угодно можешь делать его иммутабельным. Если внешним, то структура _нисколько_ не меняется если методы будут не void а будут возвращать новый итератор.
Re[33]: Почему объектно-ориентированное программирование про
Здравствуйте, Sinclair, Вы писали:
S>В менее традиционных реализациях ООП, где, скажем, нет способа манипулировать "адресом" объекта, применяют OID — Object Identifier.
S>По итогам дискуссии получается, что у immutable "объектов" identity нет, то есть это не объекты с точки зрения ООП.
Реально, поскольку объекты иммутабельные, нет разницы кому посылать сообщение, следовательно можно считать любые строки "abc" одним и тем же объектом.