[Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.11 12:39
Оценка:
Всем привет.

Взглянул я тут на код StructuralEquality. Он дремучий и кривой. Данный макрос не реализует метод GetHashCode и всегда используется код "x.GetType().Equals(this.GetType())", что замедляет реализацию (особенно для структур).

Кроме того этот макрос не реализует интерфейсы IEquatable[T] и IStructuralEquatable.

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

Требования к новой реализации макроса:
1. Реализация интерфейсов IEquatable[T] и IStructuralEquatable.
2. Реализация методов Equals (типизированной) и GetHashCode.
3. Реализация макро-атрибута IgnoreInEquals (имя можно подобрать и получше).
4. Предоставление замены для "x.GetType().Equals(this.GetType())". Для структур этот код вообще не должен появляться, для класса должна быть настройка позволяющая опустить эту проверку. Кроме того такая проверка должна устраняться, если класс помечен модификатором sealed.

Кроме того предлагаю так же реализовать макрос реализующий IEqualityComparer[T] для заданного типа. Применять его так же имеет смысл к классу, но это будет класс компаратора. Сравниваемый же тип должен передаваться макросу в качестве параметра. Как вариант, можно реализовать макро-атрибут уровня сборки.
[ImplementIEqualityComparer(MyType)]
class MyTypeEqualityComparer { }

// или 

[assembly: ImplementIEqualityComparer(MyType)]


Задача не сложная, но интересная.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 17.09.11 07:19
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Кроме того предлагаю так же реализовать макрос реализующий IEqualityComparer[T] для заданного типа. Применять его так же имеет смысл к классу, но это будет класс компаратора.


А почему не к классу, для которого нужен Comparer? А для случаев когда это нгевозможно, может быть макрос уровня сборки.
Re[2]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.11 11:11
Оценка: +1
Здравствуйте, catbert, Вы писали:

C>А почему не к классу, для которого нужен Comparer?


Потому что компораторы зачастую делают для внешних типов.

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


А зачем плодить 20 вариантов? Хочется каждый раз объяснять окружающим свой витиеватый дизайн?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 17.09.11 14:00
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Кроме того этот макрос не реализует интерфейсы IEquatable[T] и IStructuralEquatable.


И operator==
Re: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 21.09.11 14:43
Оценка: 156 (1)
Здравствуйте, VladD2, Вы писали:

VD>Предлагаю кому-нибудь взяться за реализацию новой версии данного макроса, или даже лучше ряда макросов предоставляющую реализацию эквивалентности "из коробки".


Альфа-версия макроса StructuralEquality2:

http://files.rsdn.ru/92155/StructuralEquality2.zip

Умеет:
1. Реализация интерфейса IEquatable[T].
2. Реализация методов Equals (типизированной) и GetHashCode.
3. Реализация макро-атрибута EqualsIgnore и опции Ignore в макросе.
4. Код "x.GetType().Equals(this.GetType())" отключается для структур, sealed-классов и опцией.

Не умеет:
1. Отключать проверку для автосвойств и автособытий
2. Поддерживать IStructuralEquatable (нету VS2010 чтобы потестить)
3. Ну, и еще код там местами потенциально N^2

Использование:
[StructuralEquality2(CheckTypes=false, Ignore=Field1)]
class Blah
{
    
    Field1 : int;
    [EqualsIgnore] Field2 : string;
    Field3 : bool;    

}


Жду конструктивной критики.
Re[2]: [Задание] Переписать StructuralEquality
От: _nn_ www.nemerleweb.com
Дата: 21.09.11 15:10
Оценка:
Здравствуйте, catbert, Вы писали:

C>2. Поддерживать IStructuralEquatable (нету VS2010 чтобы потестить)

Сам VS2010 не нужен чтобы компилировать для .Net 4.0
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: [Задание] Переписать StructuralEquality
От: hardcase Пират http://nemerle.org
Дата: 21.09.11 15:11
Оценка: +2
Здравствуйте, catbert, Вы писали:

C>Альфа-версия макроса StructuralEquality2:


C>http://files.rsdn.ru/92155/StructuralEquality2.zip


На гитхабе было бы как-то удобнее, чтоли...
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.11 15:11
Оценка:
Здравствуйте, catbert, Вы писали:

VD>>Предлагаю кому-нибудь взяться за реализацию новой версии данного макроса, или даже лучше ряда макросов предоставляющую реализацию эквивалентности "из коробки".


C>Альфа-версия макроса StructuralEquality2:


C>http://files.rsdn.ru/92155/StructuralEquality2.zip


Э... а зачем так сложно то?

Надо было просто сделать свой форк и работать в нем. Все кому интересно могли бы клонировать его и посмореть. Если будет все ОК, то можно будет сделать pull-request и залить изменения одним нажатием.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.11 15:44
Оценка:
Здравствуйте, catbert, Вы писали:

C>Умеет:

C>3. Реализация ... и опции Ignore в макросе.

Вот это, по-моему, лишнее. Атрибут по жизни удобнее.

C>4. Код "x.GetType().Equals(this.GetType())" отключается для структур, sealed-классов и опцией.


Здорово!

А в чем глубинный смысл этого кода:
System.Collections.Generic.EqualityComparer.Default.GetHashCode($(field.Name : usesite))

?

C>Не умеет:

C>1. Отключать проверку для автосвойств и автособытий

Почему?

C>2. Поддерживать IStructuralEquatable (нету VS2010 чтобы потестить)

C>3. Ну, и еще код там местами потенциально N^2

Это не хорошо. Макры, особенно такие часто используемые могут сильно замедлить компиляцию.
Тут лучше не писать заведомо медленный код.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.11 17:05
Оценка:
Здравствуйте, catbert, Вы писали:

Для простых встроенных типов нужно избегать использования вызовов GetHashCode и Equals.

И, нельзя ли избавиться от умножений при расчете хэш-кодов? Это весьма тяжелые операции. Не думаю, что это реально даст хоть что-то для уменьшения колизий.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 21.09.11 17:14
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, catbert, Вы писали:


C>>Умеет:

C>>3. Реализация ... и опции Ignore в макросе.

VD>Вот это, по-моему, лишнее. Атрибут по жизни удобнее.


Я делал по аналогии с Record, там есть и опция и атрибут.

C>>4. Код "x.GetType().Equals(this.GetType())" отключается для структур, sealed-классов и опцией.


VD>Здорово!


VD>А в чем глубинный смысл этого кода:

VD>
VD>System.Collections.Generic.EqualityComparer.Default.GetHashCode($(field.Name : usesite))
VD>

VD>?

Это я содрал со старой реализации. Оно проверяет на null. Очевидно, стоит заменить на .?

VD>Это не хорошо. Макры, особенно такие часто используемые могут сильно замедлить компиляцию.

VD>Тут лучше не писать заведомо медленный код.

Тут просто не факт, что код с лучшей асимптотичной сложностью будет в среднем быстрее. Надо еще измерения провести

C>>Не умеет:

C>>1. Отключать проверку для автосвойств и автособытий

VD>Почему?


Потому что в Немерле:
1) из автосвойств и автособытий нельзя вытащить сгенерированное поле
2) странно работает (или вообще не работает — я так и не понял) навешивание аттрибутов и макросов на сгенерированные автосвойствами поля.

В результате, нельзя узнать, какое поле отвечает какому свойству.
Re[3]: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 21.09.11 17:15
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, catbert, Вы писали:


C>>Альфа-версия макроса StructuralEquality2:


C>>http://files.rsdn.ru/92155/StructuralEquality2.zip


H>На гитхабе было бы как-то удобнее, чтоли...


Не было доступа в Интернет
Re[4]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.11 17:45
Оценка:
Здравствуйте, catbert, Вы писали:

C>Я делал по аналогии с Record, там есть и опция и атрибут.


Да это наследие былых времен. С появлением RecordIgnor, лично я стал пользоваться только им.

C>Тут просто не факт, что код с лучшей асимптотичной сложностью будет в среднем быстрее. Надо еще измерения провести


Что там тестировать? Если возможен квадрат, то он нарисуется. Это закон Мерфи.

C>>>Не умеет:

C>>>1. Отключать проверку для автосвойств и автособытий

VD>>Почему?


C>Потому что в Немерле:

C>1) из автосвойств и автособытий нельзя вытащить сгенерированное поле

Да ладно. Они доступны без проблем. И твой код их подхватывает. Вот декомпилированный код:
// Program.Simple
[CompilerGenerated]
public override int GetHashCode()
{
    int num = 842801;
    num = 700127 * num + EqualityComparer<string>.Default.GetHashCode(this.First);
    num = 700127 * num + this.Second.GetHashCode();
    return 700127 * num + this._N_Third_3603.GetHashCode();
}


C>2) странно работает (или вообще не работает — я так и не понял) навешивание аттрибутов и макросов на сгенерированные автосвойствами поля.


Это другой вопрос. Хардкейс говорил, что навешивание атрибутов должно работать. Но может он ошибался. Надо проверять.

C>В результате, нельзя узнать, какое поле отвечает какому свойству.


Это вообще можно узнать из описания свойства. У PropertyBuilder есть свойство AutoPropertyField. В него должна помещаться ссылка на соответствующее поле.

Кроме того в макросе Record игнорирование для автосвойств работает. Так что проблем быть не должно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 21.09.11 18:04
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, catbert, Вы писали:


VD>Для простых встроенных типов нужно избегать использования вызовов GetHashCode и Equals.


Почему? И как?

VD>И, нельзя ли избавиться от умножений при расчете хэш-кодов? Это весьма тяжелые операции. Не думаю, что это реально даст хоть что-то для уменьшения колизий.


Можно В этом списке, например, есть и хеши с одними шифтами:

http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
Re[5]: [Задание] Переписать StructuralEquality
От: catbert  
Дата: 21.09.11 18:09
Оценка:
Здравствуйте, VladD2, Вы писали:

C>>Потому что в Немерле:

C>>1) из автосвойств и автособытий нельзя вытащить сгенерированное поле

VD>Да ладно. Они доступны без проблем. И твой код их подхватывает. Вот декомпилированный код:


Да, но соответствия с полями нету.

VD>Это вообще можно узнать из описания свойства. У PropertyBuilder есть свойство AutoPropertyField. В него должна помещаться ссылка на соответствующее поле.


Этого я не находил. Буду глядеть.

VD>Кроме того в макросе Record игнорирование для автосвойств работает. Так что проблем быть не должно.


Оно самым наглым образом захардкожено в MainParser.n
Re[3]: [Задание] Переписать StructuralEquality
От: hardcase Пират http://nemerle.org
Дата: 22.09.11 10:42
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, catbert, Вы писали:


VD>Для простых встроенных типов нужно избегать использования вызовов GetHashCode и Equals.


VD>И, нельзя ли избавиться от умножений при расчете хэш-кодов? Это весьма тяжелые операции. Не думаю, что это реально даст хоть что-то для уменьшения колизий.


Я делал хэширование по аналогии с хэшированием, которое генерирует C# компилятор для GetHashCode у анонимных типов.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.09.11 13:11
Оценка:
Здравствуйте, catbert, Вы писали:

VD>>Это вообще можно узнать из описания свойства. У PropertyBuilder есть свойство AutoPropertyField. В него должна помещаться ссылка на соответствующее поле.


C>Этого я не находил. Буду глядеть.


VD>>Кроме того в макросе Record игнорирование для автосвойств работает. Так что проблем быть не должно.


C>Оно самым наглым образом захардкожено в MainParser.n


В смысле?

И чем не подходит AutoPropertyField?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.11 14:09
Оценка:
Здравствуйте, catbert, Вы писали:

VD>>Для простых встроенных типов нужно избегать использования вызовов GetHashCode и Equals.


C>Почему? И как?


Вместо Equals использовать ==. Вместо хэш-кода само значение (для int) или несложные манипуляции с ним (их можно подсмотреть в Рефлекторе). Это будет в сто раз быстрее чем виртуальные вызовы.

VD>>И, нельзя ли избавиться от умножений при расчете хэш-кодов? Это весьма тяжелые операции. Не думаю, что это реально даст хоть что-то для уменьшения колизий.


C>Можно В этом списке, например, есть и хеши с одними шифтами:


C>http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx


Ну, вот хорошо бы вынести хэш-алгоритм в настройки и предоставить по возможность выбирать между быстрым и более хитрым алгоритмом. По умолчанию использовать быстрый (на базе ^ и <<), а если кому-то захочется, то использовать более хитрый. Можно даже позволять свой шаблон расчета хэш-значений задавать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [Задание] Переписать StructuralEquality
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.11 14:10
Оценка:
Здравствуйте, catbert, Вы писали:

VD>>Это вообще можно узнать из описания свойства. У PropertyBuilder есть свойство AutoPropertyField. В него должна помещаться ссылка на соответствующее поле.


C>Этого я не находил. Буду глядеть.


Что там глядеть то? Там все просто.

VD>>Кроме того в макросе Record игнорирование для автосвойств работает. Так что проблем быть не должно.


C>Оно самым наглым образом захардкожено в MainParser.n


Это гдейто?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: StructuralEquality beta (с пулл-реквестом)
От: catbert  
Дата: 28.09.11 19:05
Оценка:
Новая версия

Умеет:
1. Реализация интерфейсов IEquatable[T] и IStructuralEquatable.
2. Реализация методов Equals (типизированной) и GetHashCode.
3. Реализация макро-атрибута EqualsIgnore и опции Ignore в макросе.
4. Код "x.GetType().Equals(this.GetType())" отключается для структур, sealed-классов и опцией.
5. Отключать проверку для автосвойств

Не умеет:
1. Отключать проверку для автособытий
2. Реализовать интерфейсы для Nemerle.Builtins.Tuple (Немерле перестает собираться)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.