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

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

    Тут а вполне себе стековая переменная. И если в структуру дополнительные поля добавить, то размер вырастет. В D просто для классов иначе размер получать надо, только и всего.
    Это не эквивалентные куски кода.
    Дешный вариант:
    ExpandedWrap disabled
      Foo a = {data: 10};

    Вполне себе стековая переменная. И никаких дополнительных полей в структуру не добавляется.
    Цитата DarkEld3r @
    Скажу, что по указателю будет лежать всё тот же новый тип.
    Дык в растовском варианте в функцию тоже передается отнюдь не сам объект Foo, а указатель типа ToString, и лежит там неведомый, скрытый от посторонних глаз объект. Те же яйца вид сбоку. Синтаксический цукер.

    Добавлено
    Цитата D_KEY @
    Ну вообще у rust тут больший простор для реализации и оптимизации, соответственно.
    Возможно, я не спорю, что в Rust все плохо. Я считаю данный холивар бессмысленным, так как в конечном счете сравниваем одно и тоже.
    Сообщение отредактировано: applegame -
      Ну любой холивар бессмысленным можно назвать. Концепция trait'ов в сочетании с impl'ами и generic'ами, а так же, возможно, макросами, проста и представлена довольно ортогональными средствами. И если она при этом способна покрывать большую часть(все?) того, что решается с помощью классового ООП, перегрузки, шаблонной магии и пр. вещей, которые явно сложнее (и не эффективнее), то она, как минимум, заслуживает внимания.

      Добавлено
      Цитата applegame @
      Дык в растовском варианте в функцию тоже передается отнюдь не сам объект Foo, а указатель типа ToString, и лежит там неведомый, скрытый от посторонних глаз объект. Те же яйца вид сбоку. Синтаксический цукер.

      Тут, как мне кажется, ты излишне вдаешься в реализацию. Ты реализовал трейты с имплами через ОО-интерфейсы и врапперы. Но что ты этим показал?
        Цитата D_KEY @
        И если она при этом способна покрывать большую часть(все?) того, что решается с помощью классового ООП, перегрузки, шаблонной магии и пр. вещей, которые явно сложнее (и не эффективнее), то она, как минимум, заслуживает внимания.
        Сложнее и не эффективнее? Не согласен.
        Цитата D_KEY @
        Тут, как мне кажется, ты излишне вдаешься в реализацию. Ты реализовал трейты с имплами через ОО-интерфейсы и врапперы. Но что ты этим показал?
        Полагаю они именно так и реализованы в Rust.
          Цитата applegame @
          Они не станут классами. Как были структурами и примитивными типами, так и останутся.

          Я всё-таки уточню - результат makeToString ведь будет классом?

          Цитата applegame @
          Я считаю данный холивар бессмысленным, так как в конечном счете сравниваем одно и тоже.

          Ну почему же, я про D больше узнал, например. :)
            Цитата DarkEld3r @
            Я всё-таки уточню - результат makeToString ведь будет классом?
            Он будет интерфейсом или трейтом, как угодно. Аналог трейта ToString в Rust. Просто Rust неявно "кастует" Foo к ToString, а в D приходится явно "кастовать" при помощи makeToString.
            Сообщение отредактировано: applegame -
              Цитата applegame @
              Сложнее и не эффективнее? Не согласен.

              Не готов оспаривать утверждением в целом, но местами всё-таки поудобнее. По крайней мере, если сравнивать с плюсовыми шаблонами, в D ведь ситуация получше. Не будет, как минимум, многокилометровых ошибок.
              Да и макросы вполне мощные - регекспы, например, могут компилироваться вместе с программой, в С++ в шаблонах со строками работать удовольствия мало.

              Добавлено
              Цитата applegame @
              Он будет интерфейсом или трейтом, как угодно.

              Ну за указателем на интерфейс ведь будет класс? Ну и в расте можно переписать вот так:
              ExpandedWrap disabled
                fn foo2<T: ToString>(a: &T)

              И результат будет совсем другой. В стандартной библиотеке трейты именно так и используются. Потому что эффективнее, в общем случае.
                Цитата DarkEld3r @
                Да и макросы вполне мощные - регекспы, например, могут компилироваться вместе с программой
                В D тоже могут. Любой код D может быть выполнен compile-time, если нет зависимости от неконстантных внешних данных.

                Добавлено
                Цитата DarkEld3r @
                Ну за указателем на интерфейс ведь будет класс?
                Будет. А за трейтом, что будет?
                  Цитата applegame @
                  Сложнее и не эффективнее? Не согласен.

                  Т.е. ты не согласен, что классовое ООП, ОО-интерфейсы, шаблоны и концепты сложнее trait'ов с impl и дженериками? Хм. Мне кажется, ты лукавишь.

                  Добавлено
                  Цитата applegame @
                  Полагаю они именно так и реализованы в Rust.

                  Не знаю. Но не вижу никакого смысла выделять обертку в динамической памяти, да еще и при каждой передаче. Еще не вижу смысла заводить анонимный класс в make*. Так же можно поиграться с передачей аргументов и попробовать передавать трейты отдельно(примерно так делает haskell для тайпклассов). Но тут нужно подумать :) На asm-вывод посмотреть.

                  DarkEld3r, для rust нет чего-то вроде Compiler Explorer?
                    Цитата D_KEY @
                    Т.е. ты не согласен, что классовое ООП, ОО-интерфейсы, шаблоны и концепты сложнее trait'ов с impl и дженериками? Хм. Мне кажется, ты лукавишь.
                    Нет не лукавлю. Впрочем в плюсах, наверняка сложнее. В D - сильно сомневаюсь. Приведи примеры, напишу тебе аналоги, сравним.
                      Цитата applegame @
                      Цитата D_KEY @
                      Т.е. ты не согласен, что классовое ООП, ОО-интерфейсы, шаблоны и концепты сложнее trait'ов с impl и дженериками? Хм. Мне кажется, ты лукавишь.
                      Нет не лукавлю. Впрочем в плюсах, наверняка сложнее. В D - сильно сомневаюсь. Приведи примеры, напишу тебе аналоги, сравним.

                      Язык тут ни при чем. Речь о самих концепциях. trait задает набор методов, impl описывает их реализацию для типа. Тут нет никаких интерфейсов, абстрактных классов, классов. Тут нет иерархий наследования, виртуальных/невиртуальных методов, абстрактных методов, private/protected/public и пр. Очень много "лишней" информации уходит. Далее, шаблоны сложнее дженериков. Тут ты вряд ли будешь спорить? При этом Rust ушел от проблемы производительности дженериков в рантайме. Код генерируется. Но при этом нет сложных правил перегрузки, специализаций и т.п. Все разруливается через те же трейты, причем довольно прозрачно. И так же в статике. Концепты сложнее простого указания trait'а. impl'ы проще и декларативнее ручной реализации оберток.
                        Цитата DarkEld3r @
                        Моя мысль правда непонятна? В расте при добавлении трейта типу размер типа не меняется.

                        Цитата applegame @
                        Невероятно! Представь себе при добавлении новых интерфейсов в D размер типа тоже не меняется!

                        Точно так же и в С++. Размер изменится, только если добавить новые поля, подмешивание чистых абстрактных классов и замещение методов размер класса тоже не меняют
                          Цитата D_KEY @
                          Речь о самих концепциях. trait задает набор методов, impl описывает их реализацию для типа. Тут нет никаких интерфейсов, абстрактных классов, классов. Тут нет иерархий наследования, виртуальных/невиртуальных методов, абстрактных методов, private/protected/public и пр.
                          наследование есть, интерфейсы (они же трейты) есть, функции описанные в треатах - виртуальные и абстрактные, отсутствие private/protected/public - недостаток, а не преимущество.
                          Цитата D_KEY @
                          Далее, шаблоны сложнее дженериков. Тут ты вряд ли будешь спорить?
                          Буду спорить с тем, что ты это представляешь как преимущество. Дженерики в расте - частный случай шаблонов. Написать шаблон аналогичный дженерику ничуть не сложнее.
                          Цитата D_KEY @
                          Но при этом нет сложных правил перегрузки, специализаций и т.п.
                          Сложность правил зависит от языка, а не от концепций.
                          Цитата D_KEY @
                          Концепты сложнее простого указания trait'а. impl'ы проще и декларативнее ручной реализации оберток.
                          Концепты != растовским трейтам. Я не буду использовать концепты для примитивных дженерикообразных шаблонов. Для этого есть более простые способы указания template constraints. И уж тем более я не буду городить оберток без крайней необходимости. Опять же для реализации аналогичного растовскому функционала не нужно никаких особых оберток. Тот пример, который я привел - имитация растовских трейтов. Такие декораторы не часто нужены в реальной жизни

                          А вообще, это все пустые разговоры, приведи пример, где на Rust все пишется проще, чем на D.

                          Добавлено
                          Цитата amk @
                          Точно так же и в С++. Размер изменится, только если добавить новые поля, подмешивание чистых абстрактных классов и замещение методов размер класса тоже не меняют
                          В целом, да. Но ЕМНИП это implementation defined. Стандарт C++ разве требует чтобы потомок имел тот же размер, что и предок, в случаях когда не добавляются дополнительные данные?
                          Сообщение отредактировано: applegame -
                            Цитата applegame @
                            наследование есть

                            Нет. Есть возможность для trait'а указать, что его реализация типом требует так же реализации других трейтов.

                            Цитата
                            интерфейсы (они же трейты) есть

                            Допустим(а интерфейсы в D могут иметь реализацию методов по умолчанию?), но кроме них-то нет ничего. Никаких абстрактных классов, например.

                            Цитата
                            функции описанные в треатах - виртуальные и абстрактные

                            Виртуальные или абстрактные. Да. Но это не нужно указывать, об этом не нужно думать, как о каком-то отдельном механизме. Просто trait.

                            Цитата
                            отсутствие private/protected/public - недостаток, а не преимущество

                            При наличии модульной системы это довольно спорно.

                            Цитата
                            Буду спорить с тем, что ты это представляешь как преимущество.

                            Не теряй контекст, мы о простоте.

                            Цитата
                            Дженерики в расте - частный случай шаблонов.

                            Нет. Дженерики - это параметрический полиморфизм, который, в общем случае, шаблонами не покрывается.

                            Цитата
                            Написать шаблон аналогичный дженерику ничуть не сложнее.

                            Помнишь пример с контролем равенства размера двух списков/векторов во время компиляции?

                            Цитата
                            Цитата D_KEY @
                            Но при этом нет сложных правил перегрузки, специализаций и т.п.
                            Сложность правил зависит от языка, а не от концепций.


                            Если ты вводишь в язык перегрузку, полноценные шаблоны и специализации, то правила уже простыми не будут.

                            Цитата
                            Концепты != растовским трейтам.


                            Не равны. И? Вопрос в том, позволяет ли сочетание более простых и ортогональных средств в Rust решать те же задачи проектирования и управления сложностью, что мы решаем с помощью сложных и связных компонентов в более "классических" языках, без потери эффективности как в работе, так и в производительности систем?

                            Цитата
                            А вообще, это все пустые разговоры, приведи пример, где на Rust все пишется проще, чем на D.


                            Так в Rust вообще нет сложных концепций. Тут скорее ты должен привести пример, когда нам нужно все это многообразие средств и их мощность.
                              Цитата applegame @
                              В D тоже могут. Любой код D может быть выполнен compile-time, если нет зависимости от неконстантных внешних данных.
                              Ну я специально про С++ уточнил - там ведь со строками в шаблонах нормально работать нельзя. А можно простой пример шаблона в D, который со строкой работает?

                              Цитата applegame @
                              Будет. А за трейтом, что будет?
                              Будет структура содержащая указатель на данные и таблицу виртуальных функций. Но я не придираюсь, если что, просто хотел уточнить правильно ли понимаю происходящее в D.

                              Кстати, поигрался немного с трейтами в D - в ideone если одна из требуемых функций имеет неподходящую сигнатуру, то компилятор не очень понятно ругается:
                              template prog.test(Range) if (isInputRange!(Range)) does not match any function template declaration
                              То есть не показывает, что именно не подходит. Это там компилятор такой или везде так?

                              В расте, конечно, механизм "немного" другой, но если трейт не реализован, то компилятор так и скажет (the trait `...` is not implemented for the type `...`). Если же попытаться неправильно реализовать трейт, то тоже будет явное указание на проблему. Или "not all trait items implemented, missing: `drop`" или указание на неправильную сигнатуру конкретного метода.

                              Кстати, ещё один вопрос - в С++ ведь нельзя шаблонным параметрам-функциям нормально ограничить сигнатуру. В смысле можем или так или так:
                              ExpandedWrap disabled
                                template <typename F>
                                void f(F f) {}
                                 
                                void f(const std::function<int (int)>& f) {}
                              А в D можно для шаблонов явно сигнатуру требовать?

                              Цитата D_KEY @
                              Т.е. ты не согласен, что классовое ООП, ОО-интерфейсы, шаблоны и концепты сложнее trait'ов с impl и дженериками? Хм. Мне кажется, ты лукавишь.
                              На мой взгляд, в расте при написании дженериков сильнее с типами "бороться" надо. в С++, в этом плане, проще - если шаблон не будет никуда наружу торчать, то можно не париться с концептами/статик асертами и т.д. Сигнатуры, опять же, сильнее "замусориваются" разными требованиями. Для внешних функций оно, пожалуй, хорошо (хотя всё равно найдутся те, кто будут ныть про нечитаемость/сложность), но побыстрому набросать шаблон уже не выйдет.

                              Цитата D_KEY @
                              DarkEld3r, для rust нет чего-то вроде Compiler Explorer?
                              Дык - play.rust-lang.org. Там и асмовый и ллвмный выхлоп посмотреть можно. Явно флаги компиляции задавать нельзя, но дебаг/релиз переключать можно.

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

                              Добавлено
                              Цитата D_KEY @
                              Речь о самих концепциях.
                              Ну... я хоть и защищаю тут раст, но не торопился бы с выводами. :)

                              Одну сложность убрали, другую добавили. Скажем, в С++ шаблону класса дополнительный параметр можно "просто так" довесить и не париться, а раст требует, чтобы все параметры были задействованы. Конечно, необходимое сделать можно, но более явно - через PhantomData, но это ведь тоже, своего рода, "лишние приседания. Система типов, опять же, выглядит более сложной.

                              Опять же, за безопасность приходится платить тем, что многие структуры данных пишутся заметно сложнее - с привлечением unsafe, если мы хотим такой же эффективности как в С++.

                              Добавлено
                              Цитата amk @
                              Точно так же и в С++.
                              Да, мы уже разобрались. Просто говорили немного о разном. :)
                              Сообщение отредактировано: DarkEld3r -
                                DarkEld3r, я выводов о том, как это будет на практике, не делал. понятно же, что за все нужно чем-то платить. И вообще, см. подпись :)
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (33) « Первая ... 6 7 [8] 9 10 ...  32 33


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