Re[8]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 10:04
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Как раз в большинстве вариантов нужны свои сравнения.


Зачем говорить очевидную чушь? На хрена в большинстве случае нужно что-то за пределами структурной эквивалентности? В большинстве случаев её за глаза хватает. А оставшиеся 5% можно и вручную реализовать.

Ну и повторенное утверждение не становится от этого вернее.

S>Опять же Хэш код вычислять нужно время. А нужно то всего на всего сравнить ссылки


Ну все, тогда для строк эквивалентность не надо было делать. Аргументация как у девочки.

S>Я вот не помню когда пользовался односвязными списками вообще, только для буферов (страниц)


Ну как бы это твои проблемы. А так-то ими можно всегда пользоваться. Они обеспечивают неизменяемость, версионность, сравнение паттернматчингом (в нормальных языках) и всего на несколько процентов менее эффективны в случае когда нужно последовательное хранение.

S> А так тебе придется для строк свои реализации с IgnoreCase делать итд.


Чего? Это то тут причем? Компараторы и перегрузки Equals никто не отменял.

S>Для списка достаточно по дефолту ReferenceEquals


Ну глупое решение принятое глупыми людьми. Зачем его поддерживать то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 19.10.2023 10:12 VladD2 . Предыдущая версия .
Re[5]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 10:10
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Чтобы экземпляр наследника вдруг не смог бы быть равен экземпляру базового типа.

VD>А чем им для этого GetType() не подошел?

Видимо тем, что `EqualityContract` можно объявить и/или override-нуть явно:

using System;

var r = new R("A");
var x = new X("A");
Console.WriteLine($"Compare {nameof(r)} and {nameof(x)}: {r == x}"); // True

record R(string Name) { }
record X(string Name) : R(Name) {
  protected override Type EqualityContract => typeof(R);
}


VD>Да и для структурной эквивалентности (что и должна обеспечиваться для записей) не нужно совпадение типов. Достаточно совпадения полей и их значений. Так что это должно быть как опция.


В случае, когда мы допускаем, что экземпляр `record A { }` может быть "эквивалентен" экземпляру `record B : A { }` или даже `record C { }`, мне кажется, всё сильно усложнится. Как минимум, как-то вручную придётся беспокоиться о том, что `a.Equals(b) == b.Equals(a)` и `a.GetHashCode() == b.GetHashCode()` где `a` и `b` экземпляры различных типов.

Когда же ты явно переопределил `EqualityContract`, то тем самым ты заявил, что принимаешь все эти риски. Автоматически же компилятору поддерживать подобное (особенно в случае различных иерархий типов) в согласованном состоянии будет сложно.
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 10:47
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>…Да и для структурной эквивалентности (что и должна обеспечиваться для записей) не нужно совпадение типов. Достаточно совпадения полей и их значений. Так что это должно быть как опция.


Кажется, хороший пример нашёлся, объясняющий почему мне лично такое вот "структурной эквивалентности … не нужно совпадение типов" не нравится "по дефолту":
abstract record Expression { }
abstract record BinaryExpression(Expression Left, Expression Right) : Expression { }
sealed record BinaryPlusExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right) { }
sealed record BinaryMinusExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right) { }


Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.

Возможно, это вопрос терминологии и для рекордов не стоит применять понятие такой вот "структурной эквивалентности".
Help will always be given at Hogwarts to those who ask for it.
Отредактировано 19.10.2023 11:19 _FRED_ . Предыдущая версия .
Re[6]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 13:29
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.


Так это не структурная типизация, а номинативная. В структурной все определяется значениями, а не типами. Введи поле с символом (+/-) и все встанет на свои места.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 17:03
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.


VD>Так это не структурная типизация, а номинативная. В структурной все определяется значениями, а не типами. Введи поле с символом (+/-) и все встанет на свои места.


Да, я понимаю. Говорю о том, что у рекордов такая типизация смотрелась бы странно для меня. Как минимум потому, что рекорды (как и другие пользовательские типы) помимо собственно данных содержат и определённое пользователем поведение, которое имеет право быть разным в разных типах и считать такие объекты одинаковыми "из коробки" было бы неожиданным.

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

Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 20:41
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?


В целом, да. Вот только в стандартных на это забили. Да и культура у дотнетных программистов явно не та, что показывает данная тема. Всем естественно противоестественное поведение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 20.10.23 06:54
Оценка: 78 (1) +1
Здравствуйте, VladD2, Вы писали:

_FR>>Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?

VD>В целом, да. Вот только в стандартных на это забили. Да и культура у дотнетных программистов явно не та, что показывает данная тема. Всем естественно противоестественное поведение.

Да тут совсем не в "культуре" дело, а в именно в том, что "в стандартных на это забили" и теперь уже есть то, что есть. И ломать это проблематично и люди просто не ожидают иного.

Решить это в целом вполне возможно:
  1. Выписать `IEqualityComparer`-ы для коллекций (имеющихся) вместо новых коллекций.
  2. Найти удобный способ связать компаратор с полем/свойством рекорда. Атрибут или приватное свойство с именем `<PropertyName>EqualityComparer` или что-то ещё или даже всё вместе.
  3. Сделать Source Generator. который вместо дефолтового компаратора будет брать тот, что указан выше.

Возможно, найдя хорошее решение для второго пункта, можно предложить его разработчикам языка.
Help will always be given at Hogwarts to those who ask for it.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.