и ещё про рекорды..
От: MadHuman Россия  
Дата: 15.09.20 16:13
Оценка:
Господа, поясните по рекордам...

я не понял, как же они будут дефайнится..
public data class Person(string FirstName, string LastName);
или
public record Person(string FirstName, string LastName);
?


и как сравниваются?

public record Person1(string FirstName, string LastName);
public record Person2(string LastName, string FirstName);

var r1 = new Person1("Ivan", "Jonson");
var r2 = new Person1("Jonson", "Ivan");
Console.WriteLine(r1==r2); // что тут?

налицо движение к тру структурному типу, то есть главное структура контента.
по логике (если это структурный тип и сравнение структурное) от порядка дефайнинга полей результат не должен зависеть.
зависит ли сравнения от порядка дефайнинга полей в предлагаемых рекордах? если да, почему?


теперь ещё интереснее, добавляем
public record Person3(string FirstName, string LastName, string MiddleName);

можно ли кастовать Person3 к Person1?
по логике структурных типов, да, тк Person3 по сути более широкий тип чем Person1.
а как в предлагаемых рекордах? и почему?

допустим что можно кастовать, тогда как в таком случае?
var r1 = new Person1("Ivan", "Jonson");
var r3 = (Person1)(new Person3("Ivan", "Jonson", "Petrovich"));
Console.WriteLine(r1==r3); // будут равны?
вот тут уже хз.. если смотреть на них как на рекорды типа Person1, то вроде равны.
но если смотреть полностью на контент, то не равны, тк r3 содержит всё таки доп мембер...
Re: и ещё про рекорды..
От: _FRED_ Черногория
Дата: 15.09.20 16:43
Оценка: +2
Здравствуйте, MadHuman, Вы писали:

MH>Господа, поясните по рекордам...


https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md, не так давно Language Version History причесали.
На https://sharplab.io/ уже давно можно пробовать прям с мастера.

MH>я не понял, как же они будут дефайнится..


Вот так вот
MH>public record Person(string FirstName, string LastName);


MH>и как сравниваются?


По ссылке выше есть

The record type includes synthesized == and != operators…


MH>налицо движение к тру структурному типу, то есть главное структура контента.

MH>по логике (если это структурный тип и сравнение структурное) от порядка дефайнинга полей результат не должен зависеть.
MH>зависит ли сравнения от порядка дефайнинга полей в предлагаемых рекордах? если да, почему?

Было бы странно, если бы точка с координатами (5, 7) была бы равна точке с координатами (7, 5)

MH>теперь ещё интереснее, добавляем

MH>public record Person3(string FirstName, string LastName, string MiddleName);


MH>можно ли кастовать Person3 к Person1?

MH>по логике структурных типов, да, тк Person3 по сути более широкий тип чем Person1.
MH>а как в предлагаемых рекордах? и почему?

Рекорды поддерживают наследование:

Records cannot inherit from classes, unless the class is object, and classes cannot inherit from records. Records can inherit from other records.

Разные иерархии рекордов не будут приводиться одна к другой, как и разные иерархии других классов (но можно написать свои методы если нужно).

MH>допустим что можно кастовать, тогда как в таком случае?

MH>…
MH>вот тут уже хз.. если смотреть на них как на рекорды типа Person1, то вроде равны.
MH>но если смотреть полностью на контент, то не равны, тк r3 содержит всё таки доп мембер...

Встроенный механизм реализации сравнения не будет считать рекорды разных типов равными.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: и ещё про рекорды..
От: MadHuman Россия  
Дата: 15.09.20 17:02
Оценка:
Здравствуйте, _FRED_, Вы писали:


_FR>Было бы странно, если бы точка с координатами (5, 7) была бы равна точке с координатами (7, 5)

как раз ожидается что, точка с x=5, y=7 равна y=7, x=5
неважно в каком порядке я записал, важен смысл значений который выражается именем поля.
непонятно почему не сделали тру структурное сравнение для рекордов.
Re[3]: и ещё про рекорды..
От: _FRED_ Черногория
Дата: 15.09.20 17:19
Оценка: +2
Здравствуйте, MadHuman, Вы писали:

_FR>>Было бы странно, если бы точка с координатами (5, 7) была бы равна точке с координатами (7, 5)

MH>как раз ожидается что, точка с x=5, y=7 равна y=7, x=5
MH>неважно в каком порядке я записал, важен смысл значений который выражается именем поля.

Так они и равны
var point1 = new Point(X: 5, Y: 7);
var point2 = new Point(Y: 7, X: 5);
var compare = point1 == point2;


MH>непонятно почему не сделали тру структурное сравнение для рекордов.


И какой смысл вы вкладываете в сравнение точки по координатами (5, 7) и, наприрмер, вектора с этими же координатами? И, главное, откуда и зачем это знать разработчикам компилятора?
Help will always be given at Hogwarts to those who ask for it.
Re[4]: и ещё про рекорды..
От: MadHuman Россия  
Дата: 15.09.20 18:46
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Так они и равны

спасибо за ссылку, интересная тулса!

_FR>
_FR>var point1 = new Point(X: 5, Y: 7);
_FR>var point2 = new Point(Y: 7, X: 5);
_FR>var compare = point1 == point2;
_FR>

ну тут немного не тот кэйс о котором я исходно имел ввиду. тут на уровне конструктора рекорда порядок меняем.

_FR>И какой смысл вы вкладываете в сравнение точки по координатами (5, 7) и, например, вектора с этими же координатами? И, главное, откуда и зачем это знать разработчикам компилятора?

хороший вопрос ) в такой постановке действительно смысла мало.
но к примеру в F# мы можем
type Point = int * int
type Vector = int * int

let p = 1,1
let v = 1,1
let comp = v = p  //это даст тру

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

или ещё кейс когда уместно, допустим что можно создавать анонимные рекорды (щас наверно пока нельзя, но думаю к этому вопросу подойдут).
и вот тогда логично ожидать что созданные в 2х разных местах структурно идентичные рекорды, но с разным порядком дефайнинга полей, должны быть равны.
Отредактировано 15.09.2020 18:55 MadHuman . Предыдущая версия . Еще …
Отредактировано 15.09.2020 18:54 MadHuman . Предыдущая версия .
Re: и ещё про рекорды..
От: Ночной Смотрящий Россия  
Дата: 15.09.20 19:31
Оценка: +1
Здравствуйте, MadHuman, Вы писали:

MH>налицо движение к тру структурному типу, то есть главное структура контента.


Нет. Структурный тип это tuple. Record это обычный тип.

MH>можно ли кастовать Person3 к Person1?


Нет.

MH>по логике структурных типов, да, тк Person3 по сути более широкий тип чем Person1.

MH>а как в предлагаемых рекордах?

А они не структурные типы даже близко.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[5]: и ещё про рекорды..
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.20 06:00
Оценка:
Здравствуйте, MadHuman, Вы писали:
MH>то есть смысл в том, что дефенишн типа определяет его структуру. и при одинаковой структуре и одинаковых значений компонентов структуры композитные значения равны.
Для этого в дотнете уже есть туплы. Вот они как раз чисто структурно эквивалентны. У них нет никакого поведения, кроме вшитого из коробки, и нет возможности наследоваться, что могло бы приводить к коллизиям.
MH>но понятно, по сути можно считать что у каждого рекорда есть неявное поле типа Type, и за счет него даже структурно одинакоко задефайненные рекорды всё равно будут отличаться.
С учётом того, что рекорды создавались не только как "мешочек с данными" — у них может быть различное поведение, их можно наследовать — так что преимуществ у структурной эквивалентности разных типов рекордов не видно.

MH>или ещё кейс когда уместно, допустим что можно создавать анонимные рекорды (щас наверно пока нельзя, но думаю к этому вопросу подойдут).

Зачем? Чем они будут лучше анонимных классов?
MH>и вот тогда логично ожидать что созданные в 2х разных местах структурно идентичные рекорды, но с разным порядком дефайнинга полей, должны быть равны.
По-прежнему непонятно, зачем это нужно.

Было бы интересно посмотреть на пример сценария, в котором это было бы полезно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: и ещё про рекорды..
От: MadHuman Россия  
Дата: 16.09.20 08:25
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

Рекорды это дальнейшее развитие идеи туплов, когда вместо позиционной идентификации элементов переходят на именованную.

MH>>но понятно, по сути можно считать что у каждого рекорда есть неявное поле типа Type, и за счет него даже структурно одинакоко задефайненные рекорды всё равно будут отличаться.

S>С учётом того, что рекорды создавались не только как "мешочек с данными" — у них может быть различное поведение,
кмк, рекорд это в 1-ю очередь структура для данных или "мешочек с данными". То что можно прицеплять методы/поведение — это вторично.

S>их можно наследовать — так что преимуществ у структурной эквивалентности разных типов рекордов не видно.

согласен, у явно задефайненных разными типов невидно и особенно учитывая, неявное поле Type, и не надо.

MH>>или ещё кейс когда уместно, допустим что можно создавать анонимные рекорды (щас наверно пока нельзя, но думаю к этому вопросу подойдут).

S>Зачем? Чем они будут лучше анонимных классов?
тем же самым чем рекорды лучше классов. анонимность — это способ созданий/декларации.
сходу, в том же Select возвращать не анонимный класс, а рекорд

MH>>и вот тогда логично ожидать что созданные в 2х разных местах структурно идентичные рекорды, но с разным порядком дефайнинга полей, должны быть равны.

S>По-прежнему непонятно, зачем это нужно.
S>Было бы интересно посмотреть на пример сценария, в котором это было бы полезно.
Сходу затрудняюсь привести убедительный пример, но например в F# уже есть анонимные рекорды и созданные в разных местах структурно идентичные и с одинаковыми значениями компонентов такие рекорды будут равны.
Наверняка они сделаны потому что были кэйсы когда посчитали что это полезно. Можно найти ишью на гитхабе, почитать про историю их появления.
Моё интуитивное ощущение, что это правильно, такие рекорды должны быть структурно равны.
Re[7]: и ещё про рекорды..
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.20 10:05
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>Рекорды это дальнейшее развитие идеи туплов, когда вместо позиционной идентификации элементов переходят на именованную.

Имхо, это всё же другая идея, хоть и похожая на туплы. На всякий случай напомню, что в туплах с именованной идентификацией всё в порядке.
Но туплы принципиально ограничены, к примеру, в наследовании; а рекорды — нет.
И это — принципиальная штука, в отсутствие алгебраических классов: скажем, рекордами легко смоделировать иерархию классов для AST, вроде System.Linq.Expressions.Expression.
Туплами это сделать невозможно.
MH>кмк, рекорд это в 1-ю очередь структура для данных или "мешочек с данными". То что можно прицеплять методы/поведение — это вторично.
Не совсем. Если бы нам были нужны только данные, то можно было бы обойтись туплами — чего я и рекомендую делать при наличии возможности.
Сейчас у нас есть понятная логика — никакие два разноимённых рекорда не являются одинаковыми, независимо от того, являются ли их типы отнаследованными друг от друга или случайно совпадающими.

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

public record Person(name);
public record Student: Person; // тут мы ничего не добавляем
public record Teacher: Person; // и тут мы ничего не добавляем

public static bool IsSame(Person p1, Person p2)
{
  return p1.Equals(p2);
}

var s = new Student("John");
var t = new Teacher("John");

Console.WriteLine(IsSame(t, s)); // false

В структурно-эквивалентном мире p, s, и t — неразличимы, т.к. у них одинаковая структура.
Мы пишем программу, она работает корректно.
Потом мы однажды добавляем к record Student какой-то ещё атрибут — ну там, Department.
Будут ли теперь совпадать t и s хоть при каких-то параметрах конструирования? Ну там, пусть Department равен null. Отличается ли "студент без факультета" от "просто человека", если студент, по определению, "человек с факультетом"?
Какое бы решение мы не приняли, это будет континтуитивно. Если Student и Teacher потеряли эквивалентность от внесения изменений в одного из них, то написанный до этого код был крайне хрупким. Например, мы где-то делали search по списку людей, и нас вполне устраивало то, что в нём находится и студент. А потом мы немножечко поменяли код, внеся необязательное поле — и упс! Сломался какой-то совершенно отдельный от нашего кода модуль, который вообще мог быть написан не нашей командой.
Если они сохранили эквивалентность, то у нас есть большая опасность получить паразитные срабатывания там, где мы этого не ожидаем — вроде того, что прямоугольник 5*7 равен квадрату 5*5.

В общем, выглядит так, что было выбрано наименее странное решение из всех вариантов.

MH>согласен, у явно задефайненных разными типов невидно и особенно учитывая, неявное поле Type, и не надо.

Ну, "неявное поле Type" в дотнете есть у всего

MH>тем же самым чем рекорды лучше классов. анонимность — это способ созданий/декларации.

MH>сходу, в том же Select возвращать не анонимный класс, а рекорд
Повторю вопрос: чем возврат анонимного рекорда будет лучше возврата анонимного класса?
Рекорды лучше классов в том, что они позволяют писать меньше бойлерплейта для их описания. В анонимных классах бойлерплейта нету вовсе, поэтому мы ничего не сэкономим.
С точки зрения взаимодействия с остальным кодом, рекорды нам ничего не дадут. Вот мы написали
var list = from p in db.People select new {p.Name, p.Age};

list у нас теперь IQueryable<Something>.
Чем вам поможет то, что Something является анонимным рекордом, а не анонимным классом?

MH>Сходу затрудняюсь привести убедительный пример, но например в F# уже есть анонимные рекорды и созданные в разных местах структурно идентичные и с одинаковыми значениями компонентов такие рекорды будут равны.

MH>Наверняка они сделаны потому что были кэйсы когда посчитали что это полезно. Можно найти ишью на гитхабе, почитать про историю их появления.
Наверняка они сделаны такими потому, что было принято решение не делать структурную суб-типизацию; т.е. рекорды в F# не являются подтипами друг друга, ни именованные, ни анонимные.
Одним из нехороших последствий является, в частности, невозможность паттерн матчинга по ним.
MH>Моё интуитивное ощущение, что это правильно, такие рекорды должны быть структурно равны.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: и ещё про рекорды..
От: Ночной Смотрящий Россия  
Дата: 16.09.20 12:55
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>Рекорды это дальнейшее развитие идеи туплов, когда вместо позиционной идентификации элементов переходят на именованную.


Откуда такая странная идея?

MH>сходу, в том же Select возвращать не анонимный класс, а рекорд


И в чем плюс?

MH>Сходу затрудняюсь привести убедительный пример, но например в F# уже есть анонимные рекорды


Рекорды F# и рекорды C# это совершенно разные вещи.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[8]: и ещё про рекорды..
От: MadHuman Россия  
Дата: 16.09.20 16:03
Оценка:
Здравствуйте, Sinclair, Вы писали:

MH>>Рекорды это дальнейшее развитие идеи туплов, когда вместо позиционной идентификации элементов переходят на именованную.

S>Имхо, это всё же другая идея, хоть и похожая на туплы.
наверно я не четко сформулировал мысль, попробую по другому — рекорды это другой (или ещё один) способ создания композиционного типа данных. туплы — композиция за счет позиций элементов, рекорды — композиция за счет назначения элементу имени.
Такой взгляд на них безусловно существует, особенно в ФП. Другой вопрос, что выбрали за базу в C# и почему местами отошли от этой базовой идеи такого вида композирования.


S>На всякий случай напомню, что в туплах с именованной идентификацией всё в порядке.

да, но со следующими оговорками, она там больше для удобства и присутствует в рамках скоупа.
при передаче такого тупла за рамки скоупа — теряется, и в самом объекте на уровне типов не присутствует, то есть за скоупом тупл останется туплом.
да и внутри скоупа тоже.


S>Сейчас у нас есть понятная логика — никакие два разноимённых рекорда не являются одинаковыми, независимо от того, являются ли их типы отнаследованными друг от друга или случайно совпадающими.

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

S>
S>public record Person(name);
S>public record Student: Person; // тут мы ничего не добавляем
S>public record Teacher: Person; // и тут мы ничего не добавляем

S>public static bool IsSame(Person p1, Person p2)
S>{
S>  return p1.Equals(p2);
S>}

S>var s = new Student("John");
S>var t = new Teacher("John");

S>Console.WriteLine(IsSame(t, s)); // false
S>

S>В структурно-эквивалентном мире p, s, и t — неразличимы, т.к. у них одинаковая структура.
это смотря как интерпертировать тип рекорда, если как — неявный (или явный) мембер Type рекорда, то структура хоть и одинаковая — значения за счет разного типа будут разные.
всё норм, граблей нет.
повторюсь — в явно типизированных рекордах, я согласен что считать их разными это ок (именно за счет поля Type).


S>Повторю вопрос: чем возврат анонимного рекорда будет лучше возврата анонимного класса?

S>Рекорды лучше классов в том, что они позволяют писать меньше бойлерплейта для их описания. В анонимных классах бойлерплейта нету вовсе, поэтому мы ничего не сэкономим.
S>С точки зрения взаимодействия с остальным кодом, рекорды нам ничего не дадут. Вот мы написали
S>
S>var list = from p in db.People select new {p.Name, p.Age};
S>

S>list у нас теперь IQueryable<Something>.
S>Чем вам поможет то, что Something является анонимным рекордом, а не анонимным классом?
например тем, что получив аналогичный рекорд от другого квери/джсона/функции, я могу их просто естественным образом сравнивать.
если явно задефайненные рекорды разных типов можно считать разными (т.к. есть информация что тип то разный), то в анонимном рекорде — нет, нет информации что они представляют разные сущности.
Re[9]: и ещё про рекорды..
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.20 05:11
Оценка:
Здравствуйте, MadHuman, Вы писали:
MH>например тем, что получив аналогичный рекорд от другого квери/джсона/функции, я могу их просто естественным образом сравнивать.
Вы можете это делать и сейчас.

var a = from s in new[] { "a", "b", "c" } select new { H = s.ToUpper(), L = s.ToLower() };
var b = from s in new[] { "q", "a", "z" } select new { H = s.ToUpper(), L = s.ToLower() };
var d = a.Except(b);

Какие ещё сценарии применения анонимных рекордов вы видите?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: и ещё про рекорды..
От: MadHuman Россия  
Дата: 17.09.20 07:07
Оценка:
Здравствуйте, Sinclair, Вы писали:

MH>>например тем, что получив аналогичный рекорд от другого квери/джсона/функции, я могу их просто естественным образом сравнивать.

S>Вы можете это делать и сейчас.
S>

S> var a = from s in new[] { "a", "b", "c" } select new { H = s.ToUpper(), L = s.ToLower() };
S> var b = from s in new[] { "q", "a", "z" } select new { H = s.ToUpper(), L = s.ToLower() };
S> var d = a.Except(b);

забавно, незнал что анонимные классы сравниваются по контенту.
интересно почему?

но —

var p1 = new { X = 1, Y = 2};
var p2 = new { Y = 2, X = 1};
Console.WriteLine(p1.Equals(p2)); // не равны

то есть структурное равенство не соблюдается. придется задумываться откуда и как была точка (сравниваемые данные) получена чтобы их сравнить.
недостаточно только структурной эквивалентности.
Re[11]: и ещё про рекорды..
От: Ночной Смотрящий Россия  
Дата: 17.09.20 07:43
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>то есть структурное равенство не соблюдается


Структурное равенство вовсе не обязательно должно быть нечувствительно к порядку, хотя, как правило, так и есть. Но здесь проблема в том что система типов для дотнета уже задана, и вариант F#, библиотеки которого из других языков использовать практически невозможно, для мейнстрим языка не годится. Анонимные типы довольно прозрачно транслируются в обычные классы, и отказ от фиксации порядка декларации приведет к сильному усложнению всей механики.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.