
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.30] |
![]() |
|
Страницы: (33) « Первая ... 5 6 [7] 8 9 ... 32 33 ( Перейти к последнему сообщению ) |
Сообщ.
#91
,
|
|
|
Цитата applegame @ Твои реализации трейта ToString для Foo и Bar - это фактически порождение новых типов "унаследованных" от абстрактного трейта ToString и содержащих данные. Ну покажи где тут создаётся тип. Особенно удобно будет, если понадобится несколько интерфейсов так "добавить". Я думаю ты видишь разницу между D-шными трейтами и тем, что в С++ костылять можно. А ведь формально тоже "можно сделать, просто на более низком уровне". Вообще я не хочу сказать, что в расте прямо уж шедеврально и сильно оригинально сделали, но с учётом всех языковых возможностей получилось вполне неплохо. И подозреваю, что отталкивались они как раз от дженериков. И если захотели именно "более строгие шаблоны", то трейты тут вполне разумное решение. Повторюсь - насколько оно удобно на практике будет не уверен, ничего большого на расте не писал. |
Сообщ.
#92
,
|
|
|
А можно в разных частях программы на Rust иметь разные реализации одного трейта для одного типа?
|
Сообщ.
#93
,
|
|
|
Цитата MyNameIsIgor @ А можно в разных частях программы на Rust иметь разные реализации одного трейта для для одного типа? В разных модулях - нет, компилятор будет ругаться. В разных либах - да, из-за того, что трейты из библиотек импортируются явно. Но импортировать их под разными именами не получится, только один можно будет использовать. Ну и есть ещё одно ограничение: чтобы реализовывать трейт для типа, то или трейт или тип должны быть определены в данном "crate" (либа или исполняемый файл). Аргументируется это тем, что иначе мог бы возникнуть хаос из-за того, что "все" определяют одинаковые трейты и реализовывают их для всех подряд типов. Конечно, можно обойти обернув нужный тип и реализовав трейт для обёртки. Мне это не нравится, предпочёл бы более продвинутые механизмы импорта трейтов, хотя текущий вариант, разумеется, проще. |
Сообщ.
#94
,
|
|
|
Цитата DarkEld3r @ Ну покажи где тут создаётся тип. ![]() |
Сообщ.
#95
,
|
|
|
Цитата MyNameIsIgor @ что подразумевается под "создаётся тип"? Моя мысль правда непонятна? В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo. В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так? |
![]() |
Сообщ.
#96
,
|
|
И тебе не болеть. Желаю найти авторитетное определение термина "функция".
Цитата DarkEld3r @ Я бы перевернул. Абстрактный класс обладает большими возможностями по сравнению с интерфейсами. Но интерфейсы можно получить из абстрактных классов, не используя "лишние" возможности. Собственно поэтому интерфейсов как отдельной сущности в Плюсах и нет, просто за не надобностью. На мой взгляд, в С++ интерфейсы вполне есть, в том смысле, что их можно изображать абстрактными классами. Да, можно сказать, что у "у тру интерфейсов" есть больше ограничений и т.д. Добавлено Цитата DarkEld3r @ Вот мне тоже так показалось. Собственно концепты в Плюсах для этого же задумывались, вот только авторы идеи подошли к их архитектуре с позиции интерфейсов, чем и обломались. Новые концепты, вроде бы, выглядят куда более похожими на трейты. И если захотели именно "более строгие шаблоны", то трейты тут вполне разумное решение. |
Сообщ.
#97
,
|
|
|
Цитата DarkEld3r @ Моя мысль правда непонятна? Мысль то целиком понятна. Слова - нет. Хотя возможно, что я лишь думаю, что мысль понятна. Итак, что такое вы имеете в виду под "создание типа"? Цитата DarkEld3r @ В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo. А размер i32 тоже не изменится? Цитата DarkEld3r @ В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так? Так. И что? Добавлено Цитата Qraizer @ Желаю найти авторитетное определение термина "функция". Вы это говорите с таким смешным видом, как будто бы сами его хоть раз видели. |
Сообщ.
#98
,
|
|
|
Кстати, ещё забавный момент - в расте "пустые" типы занимают ровно 0 байт. Массивы пустых типов - тоже. То есть "костыль" они подложили именно в итерацию по массиву, а не в сами типы.
Цитата MyNameIsIgor @ Итак, что такое вы имеете в виду под "создание типа"? Я надеюсь у вопроса практический смысл имеется? Но ок, я не поленюсь ответить. То, что typeof(Foo) не равен typeof(makeToString(Foo)). Цитата MyNameIsIgor @ А размер i32 тоже не изменится? Да, не изменится. Пруф. Цитата MyNameIsIgor @ Так. И что? "И всё". В расте не так, следовательно происходят не эквивалентные вещи. |
Сообщ.
#99
,
|
|
|
Цитата DarkEld3r @ Я надеюсь у вопроса практически смысл имеется? Но ок, я не поленюсь ответить. То, что typeof(Foo) не равен typeof(makeToString(Foo)). Прикольно! Можно, например, написать функцию, и поскольку typeof(Foo) всё ещё будет не равен typeof(makeToString(Foo)), то делаем вывод: написание функции создаёт новый тип. Цитата DarkEld3r @ Да, не изменится. Пруф. Феноменально! А i64? |
Сообщ.
#100
,
|
|
|
Цитата MyNameIsIgor @ Феноменально! А i64? Более чем уверен, что если бы размер изменился, то ты с такой же радостью и апломбом продолжал свои рассуждения. Пожалуй, лучше буду игнорировать. |
Сообщ.
#101
,
|
|
|
Цитата DarkEld3r @ если бы размер изменился ![]() |
Сообщ.
#102
,
|
|
|
Цитата DarkEld3r @ У трейтов "нет размер", вернее он неизвестен. Как их хранить в массиве? Можно хранить ссылки/указатели. Я это и имел в виду. Цитата Цитата D_KEY @ Ну встроенные(несужающие) касты есть какие-то, да. Но свои сделать нельзя, если я правильно понимаю. ... Нет, только через "as" (ключевое слово): ![]() ![]() let e: i8 = 10; let ee: i32 = e; // error: mismatched types: expected `i32`, found `i8` let eee = e as i32; // OK. Ок, спасибо. Цитата А что значит "нельзя сделать свои касты"? Кто помешает, как и в С++ сделать функцию, например, my_super_cast? Можно и макрос. Ничего не мешает, только это не каст, а функция ![]() |
Сообщ.
#103
,
|
|
|
Цитата DarkEld3r @ Да вот тут:Ну покажи где тут создаётся тип. ![]() ![]() impl ToString for Foo { fn to_string(&self) -> String { format!("foo({})", self.data) } } ![]() ![]() foo(&a) Цитата DarkEld3r @ Невероятно! Представь себе при добавлении новых интерфейсов в D размер типа тоже не меняется! И sizeof будет одинаковым независимо от количества реализуемых интерфейсов! И тип по прежнему будет Foo! Только сразу не бросайся опровергать, читай далее.В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo. Цитата MyNameIsIgor @ Она возвращает ссылку на класс, которая всегда имеет один и тот же размер - размер указателя. Но какая разница? Твоя имплементация ToString для Foo это тоже фактически новый "безымянный" тип. Кстати я могу подправить makeToString и она больше не будет возвращать новых типов. Она будет возвращать интерфейс ToString. Что скажешь в этом случае?В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так? ![]() ![]() ToString makeToString(Foo foo) { class Impl : ToString { Foo payload; override string to_string() { return format("foo(%s)", payload.data); } // конструктор this(Foo foo) { payload = foo; } } return new Impl(foo); } Твой растовский foo(&a) будет эквивалентен D-шному foo(makeToString(a)). Rust неявно кастит Foo к реализации трейта ToString для Foo, и так же неявно кастит эту реализацию к абстрактному трейту ToString. В D приходится делать это явно. Забавно да? Оказывается местами наоброт Rust делает неявные касты, там где в других языках приходится делать явно. ![]() Зацени ![]() import std.stdio; ![]() ![]() import std.string; interface ToString { string to_string(); } struct Foo { int data; } auto makeToString(Foo foo) { class Impl : ToString { Foo payload; override string to_string() { return format("foo(%s)", payload.data); } // конструктор this(Foo foo) { payload = foo; } } return new Impl(foo); } void foo(ToString a) { writeln(a.to_string()); } void main() { Foo a = {data: 10}; foo(makeToString(a)); writeln(Foo.sizeof); writeln(a.sizeof); // OMG оно равно предыдущему выражению!!! Как такое могло случиться??? } Может теперь ты сможешь оценить шутку MyNameIsIgor про размер i32 ![]() |
Сообщ.
#104
,
|
|
|
Цитата D_KEY @ Ничего не мешает, только это не каст, а функция ![]() Ок, но тогда разве можно написать "свои касты" для С++/D? Цитата applegame @ Она возвращает ссылку на класс, которая всегда имеет один и тот же размер - размер указателя. Но какая разница? Вот, кстати, да - для примитивных типов и структур ещё и семантика нарушится ведь. В смысле, они станут классами. Ну и в D у тебя уже вот тут будет новый тип: ![]() ![]() auto a = makeToString(Foo(30)); В расте не так, там тип за указателем не прячется: ![]() ![]() let a: Foo = Foo { data: 10 }; Тут а вполне себе стековая переменная. И если в структуру дополнительные поля добавить, то размер вырастет. В D просто для классов иначе размер получать надо, только и всего. Цитата applegame @ Что скажешь в этом случае? Скажу, что по указателю будет лежать всё тот же новый тип. Цитата applegame @ Rust неявно кастит Foo к реализации трейта ToString для Foo Не совсем так, все трейт-обьекты представляются одинаково, но да, сути это не меняет. Цитата applegame @ Может теперь ты сможешь оценить шутку MyNameIsIgor про размер i32 ![]() Не, не смогу. Происходят всё равно разные вещи. Соглашусь, что я был не совсем корректен и при передаче по ссылке действительно будет "создаваться объект", но трейты можно с дженериками использовать и в этом случае никакие промежуточные обёртки не создаются. |
Сообщ.
#105
,
|
|
|
Цитата applegame @ Твой растовский foo(&a) будет эквивалентен D-шному foo(makeToString(a)). Ну вообще у rust тут больший простор для реализации и оптимизации, соответственно. А так да. Цитата Rust неявно кастит Foo к реализации трейта ToString для Foo, и так же неявно кастит эту реализацию к абстрактному трейту ToString. В D приходится делать это явно. Забавно да? Ну я бы не стал называть это именно кастом. |