На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (33) « Первая ... 5 6 [7] 8 9 ...  32 33  ( Перейти к последнему сообщению )  
> trait + impl vs class , навеяно Rust'ом
    Цитата applegame @
    Твои реализации трейта ToString для Foo и Bar - это фактически порождение новых типов "унаследованных" от абстрактного трейта ToString и содержащих данные.

    Ну покажи где тут создаётся тип.

    Цитата applegame @
    Де-факто тоже самое, просто на слегка более низком уровне.

    Особенно удобно будет, если понадобится несколько интерфейсов так "добавить". Я думаю ты видишь разницу между D-шными трейтами и тем, что в С++ костылять можно. А ведь формально тоже "можно сделать, просто на более низком уровне".

    Вообще я не хочу сказать, что в расте прямо уж шедеврально и сильно оригинально сделали, но с учётом всех языковых возможностей получилось вполне неплохо. И подозреваю, что отталкивались они как раз от дженериков. И если захотели именно "более строгие шаблоны", то трейты тут вполне разумное решение.
    Повторюсь - насколько оно удобно на практике будет не уверен, ничего большого на расте не писал.
      А можно в разных частях программы на Rust иметь разные реализации одного трейта для одного типа?
      Сообщение отредактировано: MyNameIsIgor -
        Цитата MyNameIsIgor @
        А можно в разных частях программы на Rust иметь разные реализации одного трейта для для одного типа?

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

        Ну и есть ещё одно ограничение: чтобы реализовывать трейт для типа, то или трейт или тип должны быть определены в данном "crate" (либа или исполняемый файл). Аргументируется это тем, что иначе мог бы возникнуть хаос из-за того, что "все" определяют одинаковые трейты и реализовывают их для всех подряд типов.
        Конечно, можно обойти обернув нужный тип и реализовав трейт для обёртки. Мне это не нравится, предпочёл бы более продвинутые механизмы импорта трейтов, хотя текущий вариант, разумеется, проще.
        Сообщение отредактировано: DarkEld3r -
          Цитата DarkEld3r @
          Ну покажи где тут создаётся тип.

          :crazy: Чтобы вы потом не спрашивали, как можно читать, чтобы доказывать, я сразу поинтересуюсь: а у ваших знакомых что подразумевается под "создаётся тип"?
            Цитата MyNameIsIgor @
            что подразумевается под "создаётся тип"?

            Моя мысль правда непонятна? В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo.

            В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так?
              Цитата MyNameIsIgor @
              А, понял откуда вы определения берёте. За сим закончим.
              И тебе не болеть. Желаю найти авторитетное определение термина "функция".
              Цитата DarkEld3r @
              На мой взгляд, в С++ интерфейсы вполне есть, в том смысле, что их можно изображать абстрактными классами. Да, можно сказать, что у "у тру интерфейсов" есть больше ограничений и т.д.
              Я бы перевернул. Абстрактный класс обладает большими возможностями по сравнению с интерфейсами. Но интерфейсы можно получить из абстрактных классов, не используя "лишние" возможности. Собственно поэтому интерфейсов как отдельной сущности в Плюсах и нет, просто за не надобностью.

              Добавлено
              Цитата DarkEld3r @
              И если захотели именно "более строгие шаблоны", то трейты тут вполне разумное решение.
              Вот мне тоже так показалось. Собственно концепты в Плюсах для этого же задумывались, вот только авторы идеи подошли к их архитектуре с позиции интерфейсов, чем и обломались. Новые концепты, вроде бы, выглядят куда более похожими на трейты.
              Сообщение отредактировано: Qraizer -
                Цитата DarkEld3r @
                Моя мысль правда непонятна?

                Мысль то целиком понятна. Слова - нет. Хотя возможно, что я лишь думаю, что мысль понятна. Итак, что такое вы имеете в виду под "создание типа"?
                Цитата DarkEld3r @
                В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo.

                А размер i32 тоже не изменится?
                Цитата DarkEld3r @
                В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так?

                Так. И что?

                Добавлено
                Цитата Qraizer @
                Желаю найти авторитетное определение термина "функция".

                Вы это говорите с таким смешным видом, как будто бы сами его хоть раз видели.
                  Кстати, ещё забавный момент - в расте "пустые" типы занимают ровно 0 байт. Массивы пустых типов - тоже. То есть "костыль" они подложили именно в итерацию по массиву, а не в сами типы.

                  Цитата MyNameIsIgor @
                  Итак, что такое вы имеете в виду под "создание типа"?

                  Я надеюсь у вопроса практический смысл имеется? Но ок, я не поленюсь ответить. То, что typeof(Foo) не равен typeof(makeToString(Foo)).

                  Цитата MyNameIsIgor @
                  А размер i32 тоже не изменится?

                  Да, не изменится. Пруф.

                  Цитата MyNameIsIgor @
                  Так. И что?

                  "И всё". В расте не так, следовательно происходят не эквивалентные вещи.
                  Сообщение отредактировано: DarkEld3r -
                    Цитата DarkEld3r @
                    Я надеюсь у вопроса практически смысл имеется? Но ок, я не поленюсь ответить. То, что typeof(Foo) не равен typeof(makeToString(Foo)).

                    Прикольно! Можно, например, написать функцию, и поскольку typeof(Foo) всё ещё будет не равен typeof(makeToString(Foo)), то делаем вывод: написание функции создаёт новый тип.
                    Цитата DarkEld3r @
                    Да, не изменится. Пруф.

                    Феноменально! А i64?
                      Цитата MyNameIsIgor @
                      Феноменально! А i64?

                      Более чем уверен, что если бы размер изменился, то ты с такой же радостью и апломбом продолжал свои рассуждения. Пожалуй, лучше буду игнорировать.
                        Цитата DarkEld3r @
                        если бы размер изменился

                        :facepalm:
                          Цитата DarkEld3r @
                          Цитата D_KEY @
                          Ну да, можно хранить в массиве.

                          У трейтов "нет размер", вернее он неизвестен. Как их хранить в массиве? Можно хранить ссылки/указатели.

                          Я это и имел в виду.


                          Цитата
                          Цитата D_KEY @
                          Ну встроенные(несужающие) касты есть какие-то, да. Но свои сделать нельзя, если я правильно понимаю.

                          ...
                          Цитата D_KEY @
                          Встроенные примитивные типы вроде приводятся(без потери точности).

                          Нет, только через "as" (ключевое слово):
                          ExpandedWrap disabled
                            let e: i8 = 10;
                            let ee: i32 = e; // error: mismatched types: expected `i32`, found `i8`
                            let eee = e as i32; // OK.



                          Ок, спасибо.

                          Цитата
                          А что значит "нельзя сделать свои касты"? Кто помешает, как и в С++ сделать функцию, например, my_super_cast? Можно и макрос.

                          Ничего не мешает, только это не каст, а функция :)
                            Цитата DarkEld3r @
                            Ну покажи где тут создаётся тип.
                            Да вот тут:
                            ExpandedWrap disabled
                              impl ToString for Foo {
                                  fn to_string(&self) -> String {
                                      format!("foo({})", self.data)
                                  }
                              }
                            Скрытый тип. То что его нигде не видно, не значит, что его нет. А вот тут происходит его неявный каст к ToString:
                            ExpandedWrap disabled
                              foo(&a)

                            Цитата DarkEld3r @
                            В расте при добавлении трейта типу размер типа не меняется. То есть в том фрагменте кода sizeof для a будет одинаковым независимо от количества реализуемых трейтов. Тип тоже, по прежнему, будет Foo.
                            Невероятно! Представь себе при добавлении новых интерфейсов в D размер типа тоже не меняется! И sizeof будет одинаковым независимо от количества реализуемых интерфейсов! И тип по прежнему будет Foo! Только сразу не бросайся опровергать, читай далее.
                            Цитата MyNameIsIgor @
                            В D функция makeToString возвращает новый "безымянный" тип и размер его уже не будет равным Foo/Bar. Ведь так?
                            Она возвращает ссылку на класс, которая всегда имеет один и тот же размер - размер указателя. Но какая разница? Твоя имплементация ToString для Foo это тоже фактически новый "безымянный" тип. Кстати я могу подправить makeToString и она больше не будет возвращать новых типов. Она будет возвращать интерфейс ToString. Что скажешь в этом случае?
                            ExpandedWrap disabled
                              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;
                            ExpandedWrap disabled
                              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 :D
                            Сообщение отредактировано: applegame -
                              Цитата D_KEY @
                              Ничего не мешает, только это не каст, а функция :)

                              Ок, но тогда разве можно написать "свои касты" для С++/D?

                              Цитата applegame @
                              Она возвращает ссылку на класс, которая всегда имеет один и тот же размер - размер указателя. Но какая разница?

                              Вот, кстати, да - для примитивных типов и структур ещё и семантика нарушится ведь. В смысле, они станут классами.

                              Ну и в D у тебя уже вот тут будет новый тип:
                              ExpandedWrap disabled
                                auto a = makeToString(Foo(30));

                              В расте не так, там тип за указателем не прячется:
                              ExpandedWrap disabled
                                let a: Foo = Foo { data: 10 };

                              Тут а вполне себе стековая переменная. И если в структуру дополнительные поля добавить, то размер вырастет. В D просто для классов иначе размер получать надо, только и всего.

                              Цитата applegame @
                              Что скажешь в этом случае?

                              Скажу, что по указателю будет лежать всё тот же новый тип.

                              Цитата applegame @
                              Rust неявно кастит Foo к реализации трейта ToString для Foo

                              Не совсем так, все трейт-обьекты представляются одинаково, но да, сути это не меняет.

                              Цитата applegame @
                              Может теперь ты сможешь оценить шутку MyNameIsIgor про размер i32 :D

                              Не, не смогу. Происходят всё равно разные вещи.

                              Соглашусь, что я был не совсем корректен и при передаче по ссылке действительно будет "создаваться объект", но трейты можно с дженериками использовать и в этом случае никакие промежуточные обёртки не создаются.
                                Цитата applegame @
                                Твой растовский foo(&a) будет эквивалентен D-шному foo(makeToString(a)).

                                Ну вообще у rust тут больший простор для реализации и оптимизации, соответственно. А так да.

                                Цитата
                                Rust неявно кастит Foo к реализации трейта ToString для Foo, и так же неявно кастит эту реализацию к абстрактному трейту ToString. В D приходится делать это явно. Забавно да?

                                Ну я бы не стал называть это именно кастом.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (33) « Первая ... 5 6 [7] 8 9 ...  32 33


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0547 ]   [ 15 queries used ]   [ Generated: 18.07.25, 14:35 GMT ]