Re[11]: IEquatable<T>
От: vdimas Россия  
Дата: 14.02.17 03:11
Оценка:
Здравствуйте, samius, Вы писали:

V>>Я не прав был, что не изучил её (простыню) всю? ))

S>Сам же и ответил. Не поняв, ЗАЧЕМ, изучил всю, вынес вердикт не о том, о чем была дана ссылка и контекст.

Потому что это было уныло — расписывать.
Я хорошо понял зачем.
Унылость была в том, что коллега не расписал свой аргумент, т.е. отвечать было не нечего, а не на что. Начался отрезок бессмыслицы в обсуждении.

Я его просто ткнул носом в слабость его аргумента и удивился потом с того, что коллега даже не понял, во что именно я его ткнул. ))
И еще показал, что я подобных флуктуаций его сознания уже ожидал:
http://www.rsdn.org/forum/flame.comp/6662410.1

Там действительно, лишь флуктуация.
Т.е. человек помнит "трюк" насчет ограничений генерик-аргументов, но не помнит, куда и как его можно применять.


V>>Вместо такого фокуса коллега мог назвать конкретный метод конкретного типа и никаких ссылок не надо — кому попервой и даже любопытно, пусть смотрит сам. А остальным, кто еще 12-15 лет назад это всё уже прожевал и выкакал, сорри, тому банально не любопытно глазеть на подобный код.

S>Коллега понадеялся что контекста обсуждения было достаточно. А в отношении любопытства остальных — согласен. Возможность — юслес на 99% (ИМХО).

Коллега не умеет формулировать свои мысли. Если бы он попытался формально расписать свой аргумент, то САМ увидел бы, что его аргумент НЕ канает. Бо в хорошем вопросе содержится половина ответа. И тут как раз тот случай.

Сам разве не обратил внимания, что между List<T> и ограничением IEquatable<T> нет никакой связи на уровне типов языка.
Он ведь правильно пишет (по наитию, скорее):

Как он (comparer) там создаётся вообще пофигу.

"Пофигу", потому что ему хочется проигнорить вот этот "разрыв" в системе типов, из-за чего, собсно, и подключается рефлексия.

Но оно не пофигу, коль он взялся опровергать вот это:

Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.

Потому что из-за отсутствия связи на уровне типов в этом месте НЕЛЬЗЯ подать value-type GenericEqualityComparer<T> where T : IEquatable<T>, даже если бы сигнатура метода была примерно такая:
class List<T> {
 public int IndexOf<TComparer>(T value, Comparer comparer) where TComparer : IEqualityComparer<T> {...}
...
}

Т.е. в этом месте можно было бы подать лишь НЕ генерик-реализацию в случае value-type компаратора, т.е. его аргумент аннигилируется без моей помощи. ))

Потому что требуемое ограничение надо было бы распространить выше:
class List<T> where T : IEquatable<T>

что являлось бы суровым ограничением.

Итого, что мы имеем:
* В самом алгоритме целевого метода используется техника, описанная мною тут и тут.

Оттуда:

я и сам смогу тебе привести сходу пример, где такой полиморфизм сможет разресолвится статически в дотнете, я уже озвучивал — это при использовании технологии "объекта-словаря операций" (и в приводимых к этой концепции сценариях), где сам такой объект представлен value-типом. Ну не популярная эта техника нифига в дотнете. Там никто не таскает в логике эти словари рядом с целевыми объектами, везде идёт попытка работать с объектами напрямую. А когда напрямую, то возвращаемся к самому первому моему утверждению:
Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях.

Потому что получается так, что лишь теми операциями, которыми обложили базу объекта (интефейс интерфейса или публичный интерфейс базового класса) и можно оперировать. И шаг вправо-влево сделать вааще никак.

Но спорить с подобными утверждениями тоже надо уметь. Пытаясь мне показать, что такие алгоритмы все-таки есть, вы показываете банальное невладение логикой.


* Мне приводят пример, где GenericEqualityComparer<T> создаётся через рефлексию, потому что система типов не позволяет указать его явно в исходнике.

* В целевом алгоритме НЕТ никакого трюка по вызову методов целевого типа T.

* Все операции делаются через т.н. "словарь операций", где сам словарь НЕ обязан быть генерик-словарём, там используется обычный ООП-интерфейс.

* вызов методов у целевого T происходит только здесь:
internal class GenericEqualityComparer<T> : EqualityComparer<T> where T : IEquatable<T>
{
    public override bool Equals(T x, T y)
    {
        if (x != null)
        {
            if (y != null) return x.Equals(y);
            return false;
        }
        if (y != null) return false;
        return true;
    }
}

Что в случае специализации в рантайме конкретным value-типом, отличным от Nullable<T2>, например, простым int (не суть важно, просто пример конкретного типа) даст вот такой код:
    public override bool Equals(int x, int y)
    {
       return x.Equals(y);
    }


Вот ЭТО и есть пример "алгоритма"?

===================
Я бы мог всё это дать сразу, но тут сработал такой момент, что когда собеседник "претендует" на некий уровень (а сходу взятый надменно-язвительный тон и регулярное переименование заголовков сообщений в некие "намеки" означает именно это, верно?), то сей "уровень" надо ж уметь поддерживать, не? ))

В общем, я не должен был всю эту банальщину тут расписывать. Ведь со стороны дотнета выступал не я. А то получается, что я должен был начать сам с собой спорить, бо оппонент за себя не тянет.


V>>Дотнет на сегодня — это уже довольно древняя технология, об этом надо таки помнить. Оно ведь даже скорее раздражает, когда собеседник пытается спорить и аргументировать вот на таком уровне.

S>80% технологий еще древнее. Если не больше.

Верно. Поэтому совсем уж заходить на банальности, а тем паче начинать плавать по ним — это банально моветон.
Тем более, плавать со "своей стороны баррикад". ))


V>>В общем, озвуч он членораздельно свой аргумент, и я сходу бы ему и ответил, почему его аргумент кривой, косой и не канает. Потому что, с начала всех начал, его пример НЕ является примером:

V>>1. там в любом случае происходит вызов метода интерфейса;
S>Вероятно, но вызов метода интерфейса не через интерфейс там тоже происходит.

И ты, Брут?
Нет, не происходит.

С точки зрения метода IndexOf, мы вызываем методы "черного ящика" — поданного извне словаря операций. Вызовы метода по ограничениям — это уже подробности реализации этого черного ящика и никак не связаны с целевым алгоритмом. Более того, уже показал выше, почему этот "черный ящик" не может иметь генерик-реализацию value-type в системе типов, т.е. у нас тут получаются ДВА независимых разных алгоритма, работающих совместно.

Т.е., мы заведомо имеем дело с "нетипизированным параметрическим полиморфизмом".
Подробно я описывал тут: http://www.rsdn.org/forum/flame.comp/6680620.1

Блин, ну вот целиком пример (заставляете тратить время на запуск Студии, бо я уже и сам начинаю сомневаться, ы-ы-ы):
    struct GenericEqualityComparer<T> : IEqualityComparer<T> where T : IEquatable<T>
    {
        public bool Equals(T x, T y)
        {
            if (x != null)
            {
                if (y != null) return x.Equals(y);
                return false;
            }
            if (y != null) return false;
            return true;
        }

        public int GetHashCode(T obj)
        {
            throw new NotImplementedException();
        }
    }

    class MyList<T>
    {
        public int IndexOf<TComparer>(T value, TComparer comparer) where TComparer : IEqualityComparer<T>
        {
            return 0; // заглушка
        }

        // Не компиллируется! 
        public int IndexOf<TComparer>(T value)
        {
            return IndexOf(value, new GenericEqualityComparer<T>());
        }
    }

А не, всё верно, не компиллируется нифига.

Кароч.
Именно из-за нетипизированной природы параметрического полиморфизма в предлагаемом МНЕ примере-аргументе мы НЕ МОЖЕМ вызывать методы типа T в теле методов MyList<T>.

Ву а ля? Или еще нет?

Но фиг с ним, это всё банальности и я в шоке, что их потребовалось расписать настолько подробно на 15-й год существования дотнета. Дело не только в этом. Различная null-default(T) семантика value и ref типов накладывает свои дополнительные ограничения и тоже резко сужает класс алгоритмов, которые можно было бы выразить прямо из Т, без прибегания к технике "словарей операций", которые, цитирую сам себя:

... в концепции дотнетного ООП такая техника выглядит заимствованием из чужеродного ФП.

Т.е., те фишки ФП, которые не руинят ООП — они в практику дотнета таскаются с удовольствием, смотрю. Остальные практики игнорятся, хотя именно такая реализация параметрического полиморфизма требует именно таких практик.

И я имел ввиду больше вот эти ограничения на разницу в семантике (в одном случае идёт прямая адресация, в другом косвенная), которые не всегда просто преодолеть — оформить непосредственно в виде генерик-кода БЕЗ прибегания к посторонним "словарям операций". Каждый такой словарь — это костыль. В С++ можно обойтись без него, в этом была суть уже моего аргумента. Хотя, можно и с таким же точно костылём — но в С++ хоть есть выбор.

В общем, всё нужное я уже более одного раза говорил ранее...
Просто топик расползся и оно местами сильно по топику раскидано. ))


V>>2. дефолтный компаратор порождается через рефлексию; особенно весело сие после пространных рассуждений коллеги о "безопасной компиляции";

S>Как создается дефолтный компарер — не имеет отношения. Тем более, что он кэшируется.

Т.е., таки, Брут. ))
Имеет в том плане, что может быть создан ТОЛЬКО через рефлексию.
Кеширован или нет — отмазки, это же просто некое инженерное решение-следствие, т.е. уже не принципиально в этом споре.
Более того, само наличие отдельного компаратора, даже для случая встроенных типов — это ой. Потому что в теле самого List<> мы беспомощны.


V>>3. коллега пытался аргументировать об одинаковой работе для случая value-type и ref-type, но приводит такой пример, где методы типа Т не вызываются вовсе, а вызываются методы исключительно ref-типа IComparer<T> (в теле генерик-метода);

S>а методы IEquatable<T> каким образом вызываются? О них ведь речь была.

Методы IEquatable<T> в целевом алгоритме не вызываются никак, даже после Джитта, увы. Вызываются методы черного ящика, причем, исключительно как виртуальные. Т.е., что там на "другой стороне" уже не принципиально.

Т.е., в обсуждаемом примере через "водораздел" ООП-полиморфизма происходит выход на ad hoc полиморфизм. А вот последний может, в свою очередь, может быть реализован и через параметрический полиморфизм и через что угодно. Одно плохо — в системе типов языка последнее невыразимо вообще никак.


V>>Этого коллеге показалось мало и его стало заносить далее: " ты даже на джуниора не потянул бы, ты совершенно не понимаешь происходящего".

V>>Мамая мия.
S>Я полагаю что вы говорили о чем-то разном, подразумевая что об одном и том же.

Я полагаю, что коллега плохо понимает, о чем речь, но обвиняет в плохом понимании окружающих.
Причем, ответвление на vector<> показало вообще кошмар в плане дедуктивных способностей и навыков ведения спора / аргументирования.

Вот тут примерно так же — вместо обсуждения сабжа коллега радостно зацепился за мою фразу "вызов Equals у базового Object", хотя к сути происходящего в методах List<T> оно вообще не имело никакого отношения. Даже само это цепляние было самоподставой (чел повелся на троллинг), ведь в системе типов языка нам доступна только реализация указанного мною ObjectEqualityComparer и я недвусмысленно на это намекал.
Похоже, ты тоже не понял тот "тонкий" троллинг с моей стороны... Но ты-то ладно, это было обсуждение не с тобой, ты не обязан вдумываться в чужие споры.

Кароч, это я уже сам себя веселил, видя полнейшую слепоту оппонента колеги Qbit86.
Просто троллинг был уже нифига не тонкий, вот в чем был самый юмор ситуации, как по мне.

Но все-равно коллега так и не увидел, в чем там собака зарыта... Ну и фиг с ним, значит и не хотел...
Но потом заканчивает своё непонимание рассуждениями о том, что я даже на джуниора не тяну.
Блин, куда катится мир?

На Украине пещерные люди отодвинули грамотных. На форуме тоже порой просто засилье, скажем так, глубоко несообразительных людей... что ваще происходит-то??? )))


V>>В итоге, коллега заслуженно был подвергнут нещадной обструкции.

V>>Причем, весьма мягкой, ИМХО, учитывая происходящее целиком. ))
S>Мягко, но нещадно. Интересно.

Мягкой по форме, нещадной по содержанию. Так бывает. ))
Можно было бы и форму попрямее выбрать, бо это всё просто сюрр для, казалось бы, аж программиста...


V>>Хотя, если упустить весь рисунок развития ситуации, согласен, моя реакция может показаться странной. Там надо на десяток постов вверх подниматься и смотреть на картинку целиком.

S>Смотрел вчера, картина не стоит того.

Я уже высказывал своё восхищение твоими манерами, но нет.

Понимаешь, дело вовсе не в том, что коллега чего-то не понимает.
Невладение какой-то инфой здесь и сейчас — оно ведь совершенно не страшно.
Я бы даже сказал — это полная ерунда, не принципиально ни разу.
Страшно, другое — когда и не хотят владеть.

Еще более страшно, когда оппонент сходу переходит к мелким гадостям — подколкам, язвительности, троллингу и т.д. и т.п. на ровном (на тот момент) месте. С чего бы это, ы?

Вот такие мелкие подлости, да еще от не слишком сообразительного человека — оно приобретает эффект синергии при формировании ответного отношения.

Это же всё личные кач-ва человека, и они тут сверкают просто как россыпь бриллиантов.
В ответ на подобные манеры я обычно включаю свою душевную простоту почти сельского парня, коим и являюсь. ))
Отредактировано 14.02.2017 3:22 vdimas . Предыдущая версия . Еще …
Отредактировано 14.02.2017 3:18 vdimas . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.