Зачем избегать друзей, или как я растерял все свои плюсы

    Привет, Хабр.


    Пару дней назад мне на глаза попался вот этот твит:



    Вкратце: в очередной раз в C++ нашли какую-то лажу, которая появилась там сама, эмержентно-конвергентно, подобно слизи из одного прочитанного мной в детстве короткого научно-фантастического рассказа, которая случайно возникла в городской канализации и выросла до универсального растворителя органики.


    Давайте разбираться, благо это будет недолго (по тексту Стандарта я прыгал не больше пары часов). И весело, ссылки на Стандарт — это всегда весело.


    Вот весь код:


    #include <cstdio>
    
    class tag;
    
    template<class>
    struct type { friend constexpr auto get(type); };
    
    template<class TKey, class TValue>
    struct set { friend constexpr auto get(TKey) { return TValue{}; } };
    
    void foo() {            // never called
      if constexpr(false) { // never true
        if (false) {        // never true
            constexpr auto call = [](auto value) { std::printf("called %d", value); };
            void(set<type<tag>, decltype(call)>{});
        }
      }
    }
    
    int main() {
      get(type<tag>{})(42); // prints called 42
    }

    Будем читать его построчно.


    class tag;

    Ну, тут всё понятно.


    template<class>
    struct type { friend constexpr auto get(type); };

    Объявляем структуру type. Заметим, что она объявляет функцию с именем get и каким-то там параметром.


    Что будет, если инстанциировать (13.9.1/1) type<T> для некоторого T? В глобальном неймспейсе (но не в глобальной области видимости, но доступная для argument-dependent lookup, это важно!) окажется объявление функции get(T) (9.8.1.2/3, 13.9.1/4), пусть и без определения (6.2/2.1).


    template<class TKey, class TValue>
    struct set { friend constexpr auto get(TKey) { return TValue{}; } };

    Объявляем структуру set. Она, в свою очередь, определяет функцию с именем get и каким-то параметром.


    Что будет, если инстанциировать set<K, V> для некоторых K, V? В глобальный неймспейс снова попадёт функция get(K), но теперь вместе с определением (6.2/2).


    void foo() {
      if constexpr(false) {
        if (false) {
            constexpr auto call = [](auto value) { std::printf("called %d", value); };
            void(set<type<tag>, decltype(call)>{});
        }
      }
    }

    Ясно, что if (false) никак не влияет на какие бы то ни было инстанциирования шаблонов, равно как и приведение типа, поэтому упростим этот фрагмент:


    void foo() {
      if constexpr(false) {
        constexpr auto call = [](auto value) { std::printf("called %d", value); };
        set<type<tag>, decltype(call)>{};
      }
    }

    Мы все знаем, что if constexpr вообще придуман для того, чтобы была простая возможность не инстанциировать заведомо некорректные темплейты. Что же здесь происходит?


    Посмотрим на определение if constexpr внимательнее: 8.5.1/2. Нас интересует сначала вот эта фраза:


    If the value of the converted condition is false, the first substatement is a discarded statement

    То есть, наша ерунда с call и set — discarded statement. Пока звучит многообещающе.


    Посмотрим на следующую фразу:


    During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

    Это единственное упоминание поведения discarded statement, и единственное упоминание случая, когда оно не инстанциируется. false, естественно, не value-dependent, но есть одно «но». Эта фраза говорит об «enclosing template entity», а у нас enclosing entity — функция foo, которая ни в коей мере не является шаблонной. Соответственно, эта фраза неприменима, и ничего никуда не выкидывается, тело if constexpr вполне себе инстанциируется.


    Дальше всё понятно. Инстанциируется тело, инстанциируется type<tag>, появляется объявление get(type<tag>) в глобальном скоупе, видимое через ADL, если аргумент имени get будет иметь тип type<tag> (снова 9.8.1.2/3). Дальше инстанциируется set<type<tag>, decltype(call)>, которая определяет функцию get(type<tag>), объявленную в момент инстанциирования type<tag>. Определение при этом возвращает новое значение типа decltype(call), а так как call ничего не захватывает, и в C++20 лямбды без списка захвата можно конструировать по умолчанию (7.5.5.1/13), то всё это будет работать. В main мы просто вызываем get(type<tag>{}), которая находит объявленную и определённую ранее get через многострадальный ADL. Она возвращает лямбду, эквивалентную call, которую мы сразу же и вызываем, передавая туда 42.


    Такие дела.


    Заметим, что ключевой момент здесь — взаимодействие discarded statement и enclosing template entity. Действительно, если заменить void foo() на template<typename> void foo(), и даже если её потом явно вызвать


    как-то так
    #include <cstdio>
    
    class tag;
    
    template<class>
    struct type { friend constexpr auto get(type); };
    
    template<class TKey, class TValue>
    struct set { friend constexpr auto get(TKey) { return TValue{}; } };
    
    template<typename>
    void foo() {
      if constexpr(false) { // never true
        if (false) {        // never true
            constexpr auto call = [](auto value) { std::printf("called %d", value); };
            void(set<type<tag>, decltype(call)>{});
        }
      }
    }
    
    int main() {
      foo<int>();
      get(type<tag>{})(42); // prints called 42
    }

    то всё сломается починится блин я не знаю что это и как это назвать у меня уже нет никаких ожиданий от плюсокода придёт в норму:


    prog.cc:23:3: error: function 'get' with deduced return type cannot be used before it is defined
      get(type<tag>{})(42); // prints called 42
      ^
    prog.cc:6:37: note: 'get' declared here
    struct type { friend constexpr auto get(type); };
                                        ^

    В общем, в C++ неймспейс-скоуп — это такое глобальное состояние, которое можно менять (через инстанциирование шаблонных структур с функциями-друзьями), и которое можно считывать (через SFINAE, detector idiom и тому подобные трюки). Интересно, можно ли это считать ещё одним тьюринг-полным языком внутри C++?


    Вообще я всё чаще ловлю себя на том, что даже не знаю, что сказать о C++. С одной стороны, плюсы — мой любимый императивный язык программирования, и на шаблончиках что-нибудь этакое навернуть я всегда за. С другой стороны — это уже какое-то безумие, когда для интерпретации программы нужно помнить, есть где-то в каком-то пункте стандарта слово template или нет, потому что от этого всё меняется. Это даже не то чтобы безумие, это просто чистое разрушение, chaotic evil. С третьей — многие и наворачивание на шаблонах считают безумием, так что, наверное, кто первый халат надел, тот и прав.


    Впрочем, конкретно в этом случае ничего нового. Техника стейтфул-метапрограммирования была открыта ещё во времена C++14, и вполне реализуема в C++11, если не 03.


    Какое решение? Его нет:


    Defining a friend function in a template, then referencing that function later provides a means of capturing and retrieving metaprogramming state. This technique is arcane and should be made ill-formed.
    Notes from the May, 2015 meeting:
    CWG agreed that such techniques should be ill-formed, although the mechanism for prohibiting them is as yet undetermined.

    Абьюзить правила языка, чтобы делать такие непотребства — плохо, пнятненько.


    Наркотики — плохо, пнятненько?


    В любом случае, счастливого кодинга!

    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 542

      +12
      подобно слизи из одного прочитанного мной в детстве короткого научно-фантастического рассказа


      Теодор Л.Томас, Кейт Вильгельм. Клон
        0

        Да, оно.

          +1
          Да уж, а моя память считает что это рассказ Кинга.
            +1
            Скорее всего вы про Серую дрянь.
              +4

              У него есть похожий, "Серая дрянь" называется.


              EDIT: Вот так, думаешь "о, точно у Кинга был же такой рассказ", гуглишь 15 минут — а тут уже написали =(

              0
              Еще был фильм Капля
                0

                А ещё недавно была новость про Physarum polycephalum

                0
                А ещё есть книжка «Мутант 59».
                  0

                  Уже хотел было Дедфуда спрашивать, что за рассказ такой и тут ваш комментарий… Спасибо :)

                  +16
                  Мне вот интересно, программисты, которые пишут подобный код, они это из вредности делают или на самом деле считают, что такой стиль элегантен?
                  В команде же программисты разного уровня, как по мне нужно писать «средне», чтоб твой код потом и без тебя легко прочитали и разобрали, дописали, может исправили.
                  А такой код мне кажется половина людей даже не поймет.
                    +11

                    Ну я в заключении написал, что даже по моему мнению это перебор.


                    С другой стороны, техника прикольная, полезно знать. Или это у меня уже стадия принятия?

                      +4
                      Это скорее штука из разряда «о, будет прикольно навернуть такое в пет-проджекте, который всё-равно скиснет через несколько месяцев»
                        0
                        1. Так не работает. Любой пет-проджект в норме замышляется как будущий гугл.
                        2. Пишется «сложный» код вот почему: если программист познаёт в языке новую (для себя) фичу, выражающую что-то более общо, кратко и т.п., пусть и сложнее понимаемо, всегда будет соблазн её заюзать — «не зря же её придумали; остальные просто не шарят, вот как я до этого момента; подниму уровень своего кода до уровня тех крутых мужиков; да, не все осилят такой код, но проблемы неосиляторов меня уже не волнуют, пусть чувствуют кто в доме папа».
                          0
                          Я говорю как получается, а не как хотелось бы)
                          Да и такой код ни одного ревью не пройдёт
                      0
                      Всё зависит от решаемых задач и требований… Иногда просто нужно как-нить завернуть, чтобы нормально решить проблему.
                        +4
                        У меня коллега тащится с подобных финтов. Постоянно мониторит разные исходники (например на gitHub) и когда удается что ни будь «дикое» найти просто заливается радостью и делится эмоциональным зарядом рассказывая как «это» работает.
                        Нет, в проекты жуть не затаскивает (ну опять же зависит от личной градации, кому жуть а кому отл. решение).
                          0

                          Мне такое тоже нравится. К сожалению, в последнее время начал замечать, что даже после объяснений не до конца понимаю, почему именно так, а лезть глубже разбираться — фатально не хватает времени. Куда прикольнее становится скрафтить веранду на даче или прикинуться HT1621 и втиснуться в разрыв линии LCD, чего-то попутно меняя в законченном устройстве :)

                          +7
                          Это может быть что-то вроде демосцены. Неприминимая на практике разминка для ума.
                            +35
                            Когда я или мои коллеги сабимитили баги компиляторов, код в примере всегда ужасен. См например мой репорт github.com/microsoft/TypeScript/issues/25642. Никто в здравом уме никогда так просто не напишет. Подобные конструкции получаются после длительгого упрощения из огромных проектов. Если бы я описал когда реально такое возникает, никто бы не стал читать issue где участвует 1500 классов. Демо пример на то и демо пример что демонструрует проблему минимальным кодом, в этом его задача. Меня всегда прикалывали чуваки которые говорят: не делай так. Я так и не делал специально, оно само по себе из разных частей проекта выросло.
                              0

                              Вы в примере хотите узнать, равно ли круглое съедобному.
                              Компилятор на это ругается. А вы ругаетесь на компилятор: он глупый, не знает про яблоки.

                                +2
                                Тем не менее компилятор шарпов, не зная что есть яблоки разрешает проверить, имея съедобный и круглый объекты, являются ли они ссылками на один и тот же объект. А TS слишком умный и пытается выделываться, в этом и проблема. В моём форке эта диагностика отключена, и никаких проблем нет.
                                  0
                                  Если быть более корректным, то компилятор не может и не должен знать о существовании яблок. Он должен понимать что множественная реализация интерфейсов — валидная часть языка. И что круглость не может исключать съедобность, а он это предположение делает. Это предположение не верно. Но другой вопрос что очень часто такая проверка возникает как раз при ошибке. Создателями языка выбрано решение что пусть мы будем чаще находить ошибки, как реальные так и ложные, чем все их будем упускать. Это решение мейнтейнеров и в этом нет ничего плохого. В конце концов лишнее приведение к any решает ситуацию. Мне такой подход не подходит потому что я транслирую код из другого языка и там уже есть такие, абсолютно валидные конструкции. К сожалению компилятор не предоставляет опций для поштучного отключения каждой диагностики, но мир опенсорса прекрасен тем что можно пойти, сделать форк компилятора, подправить и жить припеваючи. Что я с удовольствием и сделал, и с тех пор сижу на форке.
                                    0

                                    Учитывая сколько всяких равенств существует это своершенно корретная вещь.


                                    В том же шарпе чтобы сравнить круглое со съедобным нужно будет использовать ReferenceEquals, а не обычный ==.


                                    В общем, не вижу тут "бага", просто кто-то обожает всякие неявные касты и операторы которые ведут себя совершенно по разному в зависимости от контекста.

                                      0
                                      Там в обсуждениях пример есть dotnetfiddle.net/V2Eltm
                                        0

                                        Ну так я и говорю что это наоборот плохо. Я был бы рад получить тут ошибку компиляции.

                                          0
                                          Это странно. Это абсолютно корректный и валидный код. Сравнивать указатели можно не обязательно приводя к одному типу (в отличии от C++) где от типизации может сдвигаться указатель.
                                            0

                                            Чтобы сравнить указатели стоит вызвать функцию СравниУказатели(a, b), а не a == b. При вызове a == b нужно вызывать метод equal какого-нибудь интерфейса IEquitable, который очевидно в данном случае не реализован. То, что в шарпах оператор == работает не так же, как оператор + например это весьма печально.

                                              0
                                              Всегда считал и считаю что == именно сравнивает указатели, а не выполняет логическое сравнение, а equals должен быполнять именно логическое сравнение, т.е. например сравнивая прямоугольники мы через == справшиваем, это непосредственно то же самый прямоугольник? А сравнивая через equals мы справиваем, одинаковые ли прямоугольники описаны этими объектами.
                                                0

                                                Ну к сожалению это не так, и == как раз контекстно-зависимый. Для тех же структур он сравнивает значение, при реализации интерфейса IEquitable он переопределяется для опять же сравнения по значению. Поэтому я и говорю, что для сравнения по ссылке в сишарпе есть отдельная фунцкия, и было бы хорошо если бы в тс сделали так же. А то потом у вас в зависимости от боксинга может сравнение одних и тех же объектов разные результаты давать.

                                                  0
                                                  Возможно. Но как минимум в js в который таргетится тайпскрипт и с которым заявляет совместимость, это никогда не так. Тут нет перегрузки операторов совсем и == именно что тупо сравниывает указатели для сложных типов или значения для value типов. А структур нет как таковых.
                                                    0

                                                    Но тогда и сравнение с C# некорректное :)

                                              +1

                                              Проблема в том, что существует два вида сравнения:


                                              1. Два указателя указывают на один объект.
                                              2. Два указателя указывают на одинаковые объекты.

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

                                      0
                                      Вообще-то, там ===, а не ==. Т.е. мы хотим узнать, одного ли типа эти объекты, и если да, то одинаковы ли они.
                                    +5
                                    Или вот ещё прекрасное github.com/Microsoft/TypeScript/issues/14833 Это доказательство факта. Грамотным людям понятно какие далеко идущие последствия даёт такой факт. Да, студенты и как вы выразились «половина людей даже не поймёт». Но это не значит что это не нужно обсуждать.
                                      0
                                      Вот, это даже по делу применили github.com/andnp/SimplyTyped/issues/80#issuecomment-470872810
                                        +2

                                        Тьюринг-полная система типов и неразрешимый тайпчекинг — это вообще классика.


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

                                          0

                                          Да, с парсингом там всё хорошо.

                                          0

                                          А что не так с этим поведением? В общем-то случае терм некорректный. Чтобы чекнуть — можно всегда делать даункаст.

                                          +13

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


                                          Заголовок спойлера
                                          <scarcasm />
                                            +4
                                            Конечно! А еще настоящий программист никокда не напишет "&mut (x as *mut libc::c_void)", когда надо написать "(&mut x) as *mut _ as *mut *mut libc::c_void".
                                              +2

                                              Ну в моем мире может и написать. Но на счастье в моем мире можно не вылезать из сейф оберточек, с которыми и проблем таких нет.

                                                +1
                                                Хорошо, когда можно не вылезать из оберточек. В моем мире это таки малореально.
                                                  +4

                                                  Ну мы переписали скала-сервис на хаскель, а затем и на раст, получили ускорение с минуты на обработку тяжелого запроса до двух секунд, и с 2-4гб потребления до 30мб, не вылезая из этого самого сейф кода. Жалко, что в вашем мире это невозможно.




                                                  Обычно в этот момент начинают говорить, что код неправильный, скала неправильная и вот это все, если бы не одно но — все 3 версии писал один и тот же человек, и раст ему предложил лично я полгода назад, а до этого он им даже не интересовался, тогда как на скале прод писал не один год. Такие дела.

                                                    0
                                                    Рад за вас :) Кстати, ради любопытства — с минуты до двух секунд — это со скалы на раст или с хаскеля на раст? Каково вообще соотношение было между этими тремя реализациями в этом плане?
                                                      +2

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


                                                        +1
                                                        Ну хаскель тоже ничего, могет, все же получше, чем Java и Scala. Хотя конечно время выполнения хуже растовского в разы, а объем памяти — на порядок. Я-то просто на хаскеле не пишу, и вообще практически не встречаюсь с ПО на нем, было интересно сравнить. Благодарю :)
                                                          0

                                                          Интересно ещё объём кода сравнить.


                                                          А память… Я как раз написал на хаскеле мелкую штуковину, которая склеивает два файла с временными рядами по десятку гигов каждый и считает всякую статистику по минутным корзинам (за день этих корзин 1440, что поменьше миллиарда точек в исходном файле). Изначально потребление памяти было вообще константным (и я не старался так писать, оно так само получилось), как только пришлось для некоторых статистик сортировать элементы в корзине, оно выросло до этак 30 метров в пике, что, учитывая наличие корзин с миллионом-другим элементов, вполне неплохо.


                                                          Было б любопытно переписать на плюсах и посмотреть бейзлайн, но лень.

                                                            0

                                                            Емнип около 20к строк на скале, и по 5к строк на хаскелле и расте. Но нужно понимать, что на прототипах еще не весь функционал реализован что был в скале.


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

                                                          +1
                                                          Такое различие во времени между Java и Scala и между Scala и Rust?
                                                          Не может быть. Бред какой-то
                                                            +8

                                                            Это не бред, а реальная выдержка из прототипирования коммерческой компании, которая делает это не для пиара какого-либо языка, а чтобы снизить издержки. Я с вами поделился результатами, потому что мне они показались интересными. А дальше что делать с этой информацией решайте сами.

                                                              +4
                                                              Результаты без кода — просто числа, которые ничего не говорят. Разве что порождают спекуляции на тему zero-cost абстракций, что уже специфично для языков. Тоже самое касается работы с памятью. Например, числодробилки на JVM вряд ли стоит делать.

                                                              Тут интересно на сам код взглянуть. Как вообще адекватная реализация на Java может уступать в разы реализации на Scala?
                                                                +1

                                                                Я вроде написал, что реализация на джаве была неадекватная.


                                                                А коммерческий код я показать вам не могу, уж извините.

                                                                  +5
                                                                  Вспомнил шутку которая не шутка
                                                                  — По итогу jar нашего продукта занимает всего 1 мб места.
                                                                  — А почему тогда JVM весит 160+ мб?
                                                                  — Это всё zero-cost абстракции.

                                                                    0
                                                                    Как раз числодробилки на JVM делать вполне можно, скорость математических операций отличается не сильно. Мы тоже прототипировали, думали выносить ли в С++ либы некую математическую обработку. Получилось что игра не стоит свеч — преимущество в скорости плюсов было невелико (после всех прогревов JVM и JIT — порядка единиц процентов), которое полностью съедалось бы затратами на JNI.

                                                                      0

                                                                      А вы сколько времени на плюсы потратили?


                                                                      У меня нередко бывало, что несколько дней с профайлером поднимали производительность на 2-3 порядка.

                                                                        0

                                                                        А примеры кода "до-после" остались? Как-то не верится, что без изменения алгоритмов можно выжать 2-3 порядка.

                                                                          0

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


                                                                          Это, например, какой-нибудь random forest, когда начинается всякая акробатика с блочной обработкой данных, максимизацией переиспользования кеша и шины памяти, упаковкой структур, и так далее.

                                                                            0
                                                                            всякая акробатика с блочной обработкой данных, максимизацией переиспользования кеша и шины памяти, упаковкой структур, и так далее.

                                                                            В некоторой степени, это и на jvm возможно. Но код будет как на C, или ещё менее читаем.

                                                                            0
                                                                            Без изменения алгоритма, а просто изменение порядка обхода матрицы не влезающей в кэш процессора меняет производительность на 2 порядка. Если добавить оператор at() который проверяет границы массива, и если вдруг (а у меня такое было), процессор всё время ошибается в предсказании перехода, то получается 3й порядок. Если при этом ещё и не хватает TLB то получаем ещё 30-60 % пенальти. т.е. почти 4й порядок. Если добавить математику с денормализованными числами получаем ещё сопоставимую просадку по производительности. Если добавить исключения для передажи обычных, а не исключительных ситуаций получим ещё кратное пенальти. И так можно продолжать до бесконечности.
                                                                            0
                                                                            Там очень тупой алгоритм был — несколько циклов по многомерному массиву и вычисление хитрой формулы для каждого элемента. Деталей уже не помню. Плюсовый код был тупо скопирован с джавы, да там и нечего особо было менять.

                                                                            В целом с такими штуками JIT компилятор джавы вполне нормально справляется, генерируя плюс-минус такой же код как плюсовый компилятор (хотя временами все-таки чуть тупее). Так что отсутствие разницы неудивительно.
                                                                    –1

                                                                    Не верю. Скала весьма близка к железу, если не обмазываться иммутабельностью. Скорость как у Java — т.е. обычно в ~1-3 раза медленнее, чем C.


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

                                                                      0

                                                                      Ну то есть — идиоматичный Хаскелль побуждает писать код оптимальнее Скалы, а идиоматичный Раст — оптимальнее Хаскелля?

                                                                        0

                                                                        Может быть. Но я сомневаюсь, что код был "идиоматичен", и практически уверен, что код не идентичен на разных языках, а на scala вдобавок написан весьма неоптимально.


                                                                        Возможно, код на scala содержал много типичных scala-конструкций, которые работают очень медленно, и если не избегать конкретно каждой из них (например, о них не подозревая), код будет тормозить. Раз так в 50 по сравнению с оптимизированным кодом (близком к коду на C), и раз в 100 по сравнению с C.
                                                                        Не знаю, как обстоят дела в хаскеле, но, возможно, в нём меньше таких неожиданностей. А раст компилируется примерно в те же инструкции, что и аналогичный код на С.


                                                                        Также согласен с версией, высказанной в комменте ниже.

                                                                          0
                                                                          Может быть. Но я сомневаюсь, что код был "идиоматичен", и практически уверен, что код не идентичен на разных языках, а на scala вдобавок написан весьма неоптимально.

                                                                          Код был везде идеоматичный. Для случая скалы это zio/monix/местами шейплес. Вполне такая обычная скала.


                                                                          В хаскелле обычный хаскель код с MTL и расставленными атрибутами а-ля UNPACK.


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

                                                                          0
                                                                          Скорей разработчик переписывая с нуля на новом языке, уже начал смотреть свежим взглядом, но при этом обладал старым опытом.
                                                                          Так что учел возможные недостатки и недоделки, в итоге заодно получился рефакторинг :)
                                                                          0
                                                                          Полагаю, что если бы один и тот же программист три раза подряд с нуля переписал бы один и тот же функционал на одном и том же ЯП, то результаты бы всё равно с каждым разом становились бы лучше и лучше — каким бы ЯП он не пользовался. Такие сравнения можно проводить «для себя», но аппелировать к ним доказывая, что один ЯП лучше другого — ну такое себе.
                                                                            0

                                                                            Ну там как бэ не просто "ну мы тут переписали", а анализ проводился. Растовый компилятор например практически всё очень хорошо заинлайнил, 5000 строк почти все собрались в один гигантский main, в релизе только ошметки некоторых функций остались.


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


                                                                            После написания версии на расте, хаскельную тоже дописали, и получили прирост процентов 20, используя знания полученные при написании прототипа (расставление префетчей и likely на условиях), но и все.


                                                                            Переписывание одной и той же программы на одном и том же языке не даст вам никакого прироста, если вы специально не переписываете ради прироста. У нас в прототипе такой цели не стояло.

                                                                +1

                                                                Хабр контекстно-зависимый, прям автомат с памятью. Любо-дорого читать!

                                                              +5
                                                              > как по мне нужно писать «средне»

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

                                                              ЗЫ. Писать простой код — это искусство ;)
                                                                +7
                                                                Профессионалы отличаются тем что пишут простой и скучный код который поймет даже тот кто не знает язык

                                                                рано или поздно будет выбор «больше кода на простых конструкциях» (сложнее читать из-за объема) или «меньше кода на конструкциях посложнее» (сложнее читать из-за конструкций). И надо знать золотую середину.
                                                                  0
                                                                  > И надо знать золотую середину.
                                                                  Как и везде, крайности всегда плохо.
                                                                    0
                                                                    Вообще синтаксис и codestyle проекта должен решать тимлид конечно.
                                                                    Но писать
                                                                    return isset($arr['val']) ? $arr['val'] : null
                                                                    вместо
                                                                    return $arr['val'] ?? null
                                                                    на проекте с php7 по моему через чур.

                                                                    Или ипользуют xml/html для разметки когда есть markdown ( как хабр :) )

                                                                    PS. Да, иногда бывает просто по привычке вербозят код.
                                                                  +2
                                                                  Профессионалы отличаются тем что пишут простой и скучный код который поймет даже тот кто не знает язык.

                                                                  Это не всегда является значимым критерием при выборе конкретного решения задачи.


                                                                  Например, люди иногда пишут библиотеки, и оказывается полезным уметь всякие неочевидные финты. Иногда — чтобы сохранить чистый и понятный для новичка в языке API библиотеки, что особенно забавно.

                                                                    0
                                                                    Для библиотек все несколько иначе, согласен.
                                                                    Но я про конечный продукт, где порой выбор правильной библиотеки делает код намного проще кстати.
                                                                +18
                                                                O_O
                                                                … афигеть… просто нет слов.
                                                                Я уже даже перестал нервно смеяться, когда слышу что-нить вроде «С/С++? Да, чо там, простые же языки»…
                                                                Не тот язык назвали brainfuck, ох не тот… Хотя всё равно люблю его, но это какой-то капец
                                                                  +9
                                                                  Как раз С достаточно прост и определён. А вот из С++ сделали что-то удивительное и душераздирающее.
                                                                    +2
                                                                    Доооо, прост, дооо… Есть там свои тёмные места, хотя до плюсов, конечно, далеко…
                                                                      +4
                                                                      Ну, там темные места скорее в плане undefined behavior, а тут полное соответствие поведения стандарту.
                                                                        +2
                                                                        Именно. Избегай undefined behavior — проблем не будет.
                                                                        Пользуешься хаками — ССЗБ, не жалуйся.
                                                                        Ну и объем стандарта немного… Гм… Поменьше.
                                                                      +5
                                                                      int x = sizeof(int) > -1;

                                                                      Чему равен x? Даже на неявных преобразованиях базовых типов можно споткнуться.

                                                                        0

                                                                        Я дилетант, но мне думается, ответа "точно не нулю" на практике достаточно

                                                                          +3

                                                                          Для дилетанта да, но вот только это неправильный ответ :)

                                                                            0
                                                                            В сложных случаях провожу «вычислительный эксперимент»:)
                                                                            // С99
                                                                            enum E {
                                                                              E1 = 1 / ((sizeof(int) > -1) == 0), // компилируется
                                                                            };
                                                                            
                                                                            // С11
                                                                            _Static_assert(sizeof(int) > -1); // IDE красит красным))
                                                                            

                                                                            Формальное обоснование вроде простое…
                                                                            +5
                                                                            Выражение эквивалентно:
                                                                            int x = sizeof(int) > UINT_MAX;
                                                                              +1

                                                                              Если быть крайне точным, эквивалентно int x = sizeof(int) > SIZE_MAX;

                                                                                +1
                                                                                Да, вы правы. Можно так:
                                                                                int x = sizeof(int) > std::numeric_limits<size_t>::max();
                                                                            +1

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

                                                                              0
                                                                              Хочется сказать «0», но, похоже, зависит от определения size_t на конкретной платформе и компиляторе — signed или нет.
                                                                                +2

                                                                                size_t по стандарту unsigned, а вот его близнец ssize_t — signed.

                                                                                  0
                                                                                  ну, я сварщик ненастоящий. Чего-то меня засмущало «size_t is not necessarily unsigned int. It may be any suitable unsigned integral type».

                                                                                  Вот разборка этого кейса:
                                                                                  https://stackoverflow.com/questions/26957049/return-value-of-sizeof-in-c
                                                                                    +5

                                                                                    Ага. Он может быть разного размера, но обязательно unsigned.

                                                                                0
                                                                                Вы неправильно вопрос ставите. Не чему равен, а зачем так.
                                                                                В моей практике, человек который так написал, не пройдёт код-ревью скорее всего. Потому что зачем так?
                                                                                После получения от него объяснений зачем и понимания, что не будет ни undefined behavior где-то дальше по коду, ни проблем с переносимостью — можно оставить. С комментариями для потомков, кстати. В данном конкретном месте.

                                                                                  +3

                                                                                  Я вас удивлю, но этот пример переносим и не содержит UB. Значение x всегда будет 0. Выражение uint32_t x = -1 эквивалентно uint32_t x = UINT32_MAX, и этот способ используется для переносимого (!) заполнения всех битов в 1. С другой стороны, обратная операция (знаковое переполнение) уже является UB.


                                                                                  https://github.com/python/cpython/blob/v3.8.0/Modules/socketmodule.c#L2560
                                                                                  https://github.com/python/cpython/blob/v3.8.0/Python/ast_opt.c#L130
                                                                                  https://github.com/postgres/postgres/blob/REL_12_0/src/backend/utils/mmgr/dsa.c#L1234

                                                                                    0
                                                                                    О. Спрошу слегка не по теме, но близко.

                                                                                    Как сейчас принято CRC считать, раз переполнение == UB?
                                                                                      0
                                                                                      Только знаковое переполнение является UB, беззнаковое не является и поведение при нем вполне себе определено. Вы же не считаете CRC в знаковых типах, правда?
                                                                                        0
                                                                                        Спасибо. Про такой нюанс прозевел.
                                                                                        Кстати, может быть знаете, из каких соображений сделали аж UB, а не platform specific?

                                                                                        Хм, заглянул в раздел определений стандарта 13ого года (какой быстрее нагуглился) слегка прифигел от терминологии (undefined behavior и unspecified behavior). Зачем ввели базовые термины, которые в сокращениях совпадают? Не понимаю.

                                                                                        Уже много лет преследует ощущение, что язык пытаются убить, делая его всё более идиотским и переусложненным на ровном месте. А программисты сопротивляются и пишут на нем «вопреки», т.к. привыкли. А небольшой части это даже нравится — ибо можно повыпендриваться ). Но я, скорее всего не прав — просто молодость прошла и учиться стало лениво.
                                                                                      0
                                                                                      Ну нет, я же написал — «ни undefined behavior где-то дальше по коду, ни проблем с переносимостью», а не про сам пример.
                                                                                      Тем не менее, если эта штука приедет на код ревью, ей понадобится ответ на вопрос «зачем именно так».
                                                                                +1
                                                                                Когда учил, то казалось что все более-менее просто в C++. Хотя, про шаблоны я наверное только слышал тогда.
                                                                                  0
                                                                                  > Да, чо там, простые же языки»…

                                                                                  На любом языке можно наворотить, если позволить «мета программирование», так что волосы зашевеляться где угодно )
                                                                                  +16
                                                                                  Что-то мне порой начинает казаться, что на гипотетическую роль «убийцы» C++ может претендовать не тот язык, который предложит что-то радикально-новое в контексте системного программирования, а тот, который будет уметь примерно все тоже самое, но радикально уменьшит сложность за счет выкидывания всех исторически-сложившихся несуразностей и упрощения синтаксиса.
                                                                                    +8
                                                                                    будет уметь примерно все тоже самое, но радикально уменьшит сложность за счет выкидывания всех исторически-сложившихся несуразностей и упрощения синтаксиса.


                                                                                    Именно такие цели ставили создатели D.
                                                                                    К сожалению, С++ у него что-то никак убить не получается, он влачит довольно жалкое существование.
                                                                                      +12
                                                                                      Они зачем-то запихали в него GC, это была их основная ошибка.
                                                                                        –3
                                                                                        не основная. сейчас, задним умом, есть недавний опрос-фидбек — что такое хорошо и что плохо, тут это офтоп, так что при интересе найду заново и скину. в личку
                                                                                          +1
                                                                                          Буду очень благодарен, интересно почитать, шош там народ считает основной ошибкой D, если не GC.
                                                                                            0
                                                                                            И мне в личку, пожалуйста, если нетрудно.
                                                                                              +6
                                                                                              И мне. А лучше в комментариях для всех.
                                                                                                –12
                                                                                                access denied. там специфика не для неокрепших умов
                                                                                          +2
                                                                                          Walter Bright завязал D на «отключаемый» сборщик мусора, мотивируя это уменьшением сложности и отсутствием сколько-либо ощутимой просадки производительности. Только заменить C++ может язык, играющий по тем же правилам. В большинстве случаев, люди используют C++ именно потому, что им необходим полный контроль над ресурсами. А языков с GC сейчас много и они имеют гораздо большую поддержку, чем D.
                                                                                          Лично мне нравятся очень многие вещи в D, но он оставляет впечатление недостаточно проработанного языка.
                                                                                            +5
                                                                                            по-моему, как раз-таки rust и пытается зайти на поляну c++
                                                                                              +1
                                                                                              Из-за своей сложности может и не зайти.
                                                                                                +5

                                                                                                Да что все твердят про сложность раста?) Ей богу, если сравнить с С++, то раст в разы проще синтаксически.

                                                                                                  +1
                                                                                                  Чтобы где-то подвинуть С++, его убийца должен быть или намного проще, легче и надежней или намного мощней (и все равно проще, легче и надежней). Rust как-то вот просто пляшет от безопасной работы с памятью, но этого слишком мало. При этом для плюсовиков он в чем-то неожиданный, и пока овчинка выделки не стоит (чтобы переходить на него).
                                                                                                    +5

                                                                                                    Мне он не показался чем-то неожиданным после плюсов. Скорее наоборот. Пока пишешь safe-код, ощущение, словно пишешь на С++ из которого убрали боль. А unsafe вызывает боль не сильно больше, чем аналогичный код на плюсах.


                                                                                                    К тому же, безопасность работы с памятью — это устранение, ну… наверное 95% ошибок при программировании на С++?


                                                                                                    К тому же, кроме работы с памятью, Rust предоставляет:


                                                                                                    1) Кучу приятного синтаксического сахара вроде match expressions или оператора? для Result и Option (потенциально для любых монад в будущем).


                                                                                                    2) Система сборки без боли, отчаяния, криков ужаса, жуткого легаси и невероятной магии. Каждый раз когда думаю о сборке проекта в С++, глаз начинает дёргаться.


                                                                                                    3) Пакетный менеджер из коробки


                                                                                                    4) Переключение тулчейна без боли и отчаяния


                                                                                                    5) Никаких ADL, SFINAE, аргументов по умолчанию, анонимных неймспейсов, static thread_local volatile переменных, неявных целочисленных и не только кастов, strict aliasing-а, noexcept, rvale, lvalue, xvalue, богомерского std::string, ещё более богомерского std::wstring, 20-ти видов инициализации, include-файлов, и бог знает чего ещё...


                                                                                                    Нет, я люблю С++. Хотя бы и за то, что после него можно смотреть с улыбкой (и лёгким налетом грусти) на все жалобы в стиле "Python 3.8 стал таким сложным"…


                                                                                                    По итогу: раст и надёжнее, из-за того, что убрали почти все способы отстрелить себе ногу. И проще, потому что не нужно знать Make, CMake и ещё с десяток менее популярных или даже самописных систем сборки. В целом, раст наверное даже не сильно медленнее.


                                                                                                    Язык этот однозначно ещё не продакшн-рэди, по крайней мере до стандартизации ABI. Но потенциал огромный.

                                                                                                      0
                                                                                                      В целом, раст наверное даже не сильно медленнее.

                                                                                                      В этот момент я подумал "хехе" и полез искать статью. Потратил минут 10 но нашел. Рекомендую к прочтению. К после прочтения поймете, почему такая реакция :)

                                                                                                        +1
                                                                                                        Я уже в теме про C# у шарповиков спрашивал, вот спрошу у поклонника раста. Вот есть такое приложение, тот же вопрос, что и шарповикам, только про раст. Предложения «пишите на расте с биндингами» не интересны (потому что зачем тогда вообще раст, если все будет делаться через кучу совершенно лишнего unsafe кода, который просто дергает C/C++ библиотеки), интересует какой-то набор фреймворков/библиотек, которые будут написаны на расте хотя бы процентов на 80. Шарповики как-то плечами пожали, хотя, казалось бы.
                                                                                                          0

                                                                                                          Прочитаю инфу по ссылке попозже, пока что отвечу про часть:


                                                                                                          потому что зачем тогда вообще раст, если все будет делаться через кучу совершенно лишнего unsafe кода, который просто дергает C/C++ библиотеки

                                                                                                          В каком смысле зачем? На расте можно написать safe обертки над этими библиотеками, как миникм5 и уже без страха писать остальную программу. Если поддерживать такую обёртку дорого и сложно, можно тогда и переписать библиотеку, не вижу с этим проблем.


                                                                                                          Мне откровенно непонятно стремление выбросить С++ и переписать всё на раст. Тысячи человеколет на С/С++ потрачены зря что ли?). Раст потому и крут, что довольно "легко" интегрируется с Си.

                                                                                                            0

                                                                                                            А мне непонятно стремление писать на раст ради того, чтобы писать на раст. "Без страха" — не аргумент, писать на C++ тоже никто не боится, а трата времени и денег на написание бесполезных "safe оберток" вокруг C++ кода бессмысленна — проще сразу писать на C++ и само приложение. Про "лёгкость интеграции" раста уже писал, по-моему, Alexey2005, в одной из тем про раст, это совершенно лишний источник головной боли, который можно оправдать, если C/C++ кода в проекте будет, скажем, 20%, но не подавляющее большинство.

                                                                                                              0
                                                                                                              Мне откровенно непонятно стремление выбросить С++ и переписать всё на раст.
                                                                                                              Переписывать не надо. Новые проекты лучше не на С++ начинать. В будущем.

                                                                                                              если C/C++ кода в проекте будет, скажем, 20%, но не подавляющее большинство
                                                                                                              А зачем Расту С++? Одного С вполне достаточно будет.
                                                                                                                +1

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

                                                                                                                  0
                                                                                                                  По идее, разработка на идеальном Rust обойдется дешевле, чем на современном С++.
                                                                                                                    +2

                                                                                                                    "По идее?" Охохо.

                                                                                                                      0
                                                                                                                      Да, иначе в Rust (условном) не будет смысла.

                                                                                                                      Остановлюсь на этом пожалуй. А то что-то минуса в карму полетели.
                                                                                                                  0
                                                                                                                  А зачем Расту С++? Одного С вполне достаточно будет.

                                                                                                                  Ну ОК, никто вас за язык не тянул, достаточно так достаточно. Ознакомьтесь с приложением по моей ссылке выше и ответьте на вопрос, на каком инструментарии вы бы его делали при условии «80% раста, 20% C, никакого C++, так как он не нужен». Все требования к производительности, поддержке платформ и прочему, естественно, сохраняются.
                                                                                                                    0
                                                                                                                    С такими широкими требованиями пока только С++. Что касается перспектив Раста для таких задач, пусть кто-то знающий его ответит.
                                                                                                                  0
                                                                                                                  Как мне представляется, Вы предлагаете не отказываясь от самого плюсового кода, отказаться от его написания.
                                                                                                                  Я не эксперт в таких вещах, но разве переход на поголовные раст-обёртки не выведут легаси на совершенно непостижимый уровень? Боюсь, что прогресс не остановится на Расте и рано или поздно на рынок таки выйдет язык, который должен будет серьёзно уделать как минимум плюсы (вероятно, и Раст, раз они метят в одну нишу), язык, который все до сих пор именуют «убийцей плюсов». К тому моменту, если переходить на написание Раст-кода над С++ обёрнутого, количество людей, которые захотят переписать легаси из С++ + Раст над ним, будет в разы меньше тех, кто переписал/переписывает Сишное легаси.
                                                                                                                  +1

                                                                                                                  Писать десктоп-приложения на расте на текущий момент не на чем, надо брать Qt, как у вас и сделано.


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


                                                                                                                  "Без страха" — не аргумент, писать на C++ тоже никто не боится,

                                                                                                                  Ой ли? Или не боятся по ногам стрелять? Ну так страх это вещь полезная, как и боль, можно сказку про сгоревших человечков которые не тушили огонь потому что им не было больно вспомнить.


                                                                                                                  а трата времени и денег на написание бесполезных "safe оберток" вокруг C++ кода бессмысленна

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

                                                                                                                    0

                                                                                                                    "Потребности в колбасе на сегодня нет", как в старом анекдоте? :) Ну ОК.

                                                                                                                      +1

                                                                                                                      Нет, я просто честно говорю про два факта:


                                                                                                                      1. для десктоп-разработки на раст сегодня ничего предложить не может
                                                                                                                      2. десктоп-разработка на сегодняшний день не очень востребованна, можно по вакансиям глянуть. Тот же сишарп в котором равноценно есть десктоп WPF и в больше чем 90% вакансий ищут именно веб.
                                                                                                                        0

                                                                                                                        Ну понятно, что веб разработки сейчас много в процентном отношении, сайтики, онлайн-сервисы, вот это вот все. Но задач, где веб-сервис не годится, тоже хватает, их тоже надо делать. Впрочем, Qt и в веб заходит потихоньку, в 5.13 появилась поддержка wasm как одного из таргетов, пока это technology preview, но процесс идёт.

                                                                                                                          0

                                                                                                                          Ну, рецепт простой, для десктопа в 2019 году нужно брать плюсы, как ни странно :)

                                                                                                                            0
                                                                                                                            Не факт — есть наверное десяток нормальных Си-шных GUI-либ, к которым есть обертки для многих языков — выбирай для удобного себе языка.
                                                                                                                            Заодно хотелось бы уточнить, т.к. я пока не понял
                                                                                                                            В отличие от D у раста позиционирование совершенно четкое
                                                                                                                            А какое оно, можно оф.ссылку?
                                                                                                                              0

                                                                                                                              Можно — на главной странице https://www.rust-lang.org/

                                                                                                                                0
                                                                                                                                А поточнее? Я там вижу
                                                                                                                                From startups to large corporations, from embedded devices to scalable web services, Rust is a great fit
                                                                                                                                А это нифига не четкое позиционирование…
                                                                                                                                  0

                                                                                                                                  Везде, где вам нужна производительность С++ с безопасностью высокоуровневых managed-языков, либо bare metal/embedded/...

                                                                                                                                    –1
                                                                                                                                    Ясно. Третьей попытки не надо =) Слово «позиционирование» можно посмотреть в словаре.
                                                                                                                                      0

                                                                                                                                      То есть язык не может позиционироваться как "общего назначения", я правильно понимаю Вашу мысль?

                                                                                                                                        0
                                                                                                                                        Конечно может, только где тогда заявленное «позиционирование совершенно четкое»? =)

                                                                                                                                        Я и пытался выяснить эти цели.
                                                                                                                                          0

                                                                                                                                          Уточню вопрос: язык может чётко позиционироваться как "общего назначения" (т.е. "применять с успехом можно везде, если скилла хватит"), или это будет "не чётко"?

                                                                                                                              –3
                                                                                                                              для десктопа в 2019 году нужно брать плюсы

                                                                                                                              Скорее JavaScript и Electron.


                                                                                                                              А C++ — для игр разве что, и прочего полноэкранного графического софта. И то, во многом потому что Unreal Engine и прочие Unity не так-то быстро переписать на Rust.

                                                                                                                                +8
                                                                                                                                Скорее JavaScript и Electron.

                                                                                                                                Ыыы. У меня прямо сейчас Skype на десктопе полгига RAM отжирает, больше отжирает только Хром, да и то, в нем открыто где-то с десяток вкладок, а отжирает он только в три раза больше. Я еще помню времена, когда Skype жрал на порядки меньше, а умел в разы больше. Electron is Cancer ©.
                                                                                                                                  0
                                                                                                                                  А ещё при запущенном скайпе юнит тесты (правда чувствительные к свободному объему кэша процессора) у меня на ноутбуке вдвое дольше выполняются. Т.е. не только он сам скайп тупит, но ещё и заставляет кратно тупить другие процессы.
                                                                                                                        0
                                                                                                                        Писать десктоп-приложения на расте на текущий момент не на чем

                                                                                                                        В будущем подгонят druid

                                                                                                                      0
                                                                                                                      Язык этот однозначно ещё не продакшн-рэди, по крайней мере до стандартизации ABI.

                                                                                                                      Не то что плюсы.

                                                                                                                        0

                                                                                                                        Ну, скажем стоило бы сказать "до стабилизации ABI". И хоть каких-то гарантий от компилятора)

                                                                                                                          0
                                                                                                                          ну так можно сказать что есть itanium abi и все остальные отщепенцы. (msvc/pgi)
                                                                                                                            0
                                                                                                                            В смысле Rust еще не продакшн-реди, а плюсы уже не продакшн-реди?))))
                                                                                                                            0
                                                                                                                            MooNDeaR Не спорю, что Rust будет мощней (а также проще, легче и надежней). Тем более меня по его новизне и новшествам уже поправили. Но плюсовики — это же как каста со своей психологией (и так почти для любого ЯП). Они станут писать игры на Rust? Десктоп на Rust (кроме браузеров)? А сложное ПО — да, их работодатели заставят.
                                                                                                                              0

                                                                                                                              Да хз, я сам из этой "касты") Мне нравятся плюсы, нравится их просто невероятно мозговыносящие конструкции на шаблонах и макросах. Я испытываю искреннее удовольствие от приведённых в статье конструкций, НО! Это чисто академическое удовольствие, как удовольствие от решённой головоломки.


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

                                                                                                                                0

                                                                                                                                Куча народа пишут игры на Rust. Правда пока нет серьезного движка то ААА на нем мы наверное пока не увидим, но вот все остальное — пожалуйста.

                                                                                                                                  0
                                                                                                                                  Правда пока нет серьезного движка то ААА на нем мы наверное пока не увидим

                                                                                                                                  вы же представляете сколько человекочасов потрачено на какой-нибудь UE? Даже если предположить что unreal перейдут на раст сегодня, забив на поддержку, и даже если они будут пилить движок в 5 раз быстрее чем на плюсах, продукт которым можно будет пользоваться мы увидим не раньше чем лет через 5 плюс еще лет 10 обкатки на реальных проектах.
                                                                                                                                    +1

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

                                                                                                                                0
                                                                                                                                Это вот вы почти про C# сейчас сказали, ага-ага :) Ну и еще про десяток языков. Ну просто не надо делать идола из инструмента, а надо пользоваться тем, что оправданно уровнем задачи и квалификацией команды. Тогда всё будет на своих местах.
                                                                                                                                  0

                                                                                                                                  Ну, что не надо делать идолов, это да, но с остальным я не согласен:


                                                                                                                                  1) Все остальные языки используют наработки С++, чтобы упростить написание прикладных приложений. Rust же позиционируется как системный ЯП, а потому в сущности предлагает делать всё то же самое, что С++, только "правильно". Остальные попытки победить С++ всегда имели какой-нибудь фатальный недостаток, вроде GC в D или непродуманной системы типов и все такое.


                                                                                                                                  2) Жрать что дают скучненько и вгоняет в депрессию. Плюс, команду можно и дообучить, а кривизну плюсов уже не выправить. В конце концов, мы же о С++ говорим. Если человек осилил плюсы и инфраструктуру вокруг них, то разобраться с Rust не составит труда.

                                                                                                                                    0
                                                                                                                                    Ну это да, тут спорить трудно. Все хотят победить конкретно плюсы, но конкретно они уже давно монстр, каких свет не видывал, о чём и статья…

                                                                                                                                    А вот «жрать что дают скучненько» — тут важен разумный компромисс между решением конкретных задач и всем вот этим дообучением команды и прочим… Так-то и сайты на плюсах кропать никто не мешает интересненькие со встроенным сервером например, но зачем?
                                                                                                                                  +2
                                                                                                                                  К тому же, безопасность работы с памятью — это устранение, ну… наверное 95% ошибок при программировании на С++?


                                                                                                                                  Вот сильно не уверен. Не скажу за всех, но лично мне очень кажется, что страшилки про «небезопасность работы с памятью в С++» сильно преувеличены. Уже давно придумана масса вполне надёжных техник, которые от этой проблемы избавляют. По крайней мере лично в моём опыте я даже не вспомню, когда в последний раз меня это кусало… Может разве что лет 20 назад, когда только учился, да и то не факт, поскольку переход на С/С++ после ассемблера очень облегчён.

                                                                                                                                  Но вот всякие хитропопые undefined behaviour или х10 ускорение после разборки с data aliasing и т.д. и т.п. — вот это периодически случается и сейчас. Про пример в посте вообще не вспоминаю, — это ж поседеть можно, пока допрёшь что за фигня, если не сталкивался.

                                                                                                                                  Главная беда, С++, имхо абсолютно не работа с памятью (она вполне безопасна и комфортна после некоторого уровня понимания), а адски замороченный стандарт с «кучей условий мелким шрифтом, сносками и звёздочками», что как раз демонстрирует пример этого поста… Но главная беда этой главной беды в том, что она, скорее всего, практически не излечима, просто потому, что заменив сложность на простоту почти всегда неминуемо проиграешь в конечном итоге в эффективности, поскольку вся эта сложность сделана с единственной целью — позволить компилятору выжимать максимум возможной эффективности из кода.
                                                                                                                                    +4
                                                                                                                                    Не скажу за всех, но лично мне очень кажется, что страшилки про «небезопасность работы с памятью в С++» сильно преувеличены

                                                                                                                                    Тоже не скажу за всех, но Segmentation Fault на моей памяти самая частая причина почему падает плюсовое приложение.


                                                                                                                                    Уже давно придумана масса вполне надёжных техник, которые от этой проблемы избавляют.

                                                                                                                                    Никто и не отрицает, что на С++ нельзя писать хорошо. Проблема в том, что устроить состояние гонки в плюсах очень и очень просто. Получить UB на ровном месте из-за нарушения strict aliasing — еще проще. Собственно в этом и разница между С++ и Rust. На С++ сложно писать правильно, нужно следовать куче практик из Core Guidelines. На Rust нужно проделать столько же усилий, но только в обратную сторону — чтобы начать писать неправильно. И все эти места еще явно обозначить как unsafe.


                                                                                                                                    Но вот всякие хитропопые undefined behaviour или х10 ускорение после разборки с data aliasing и т.д. и т.п. — вот это периодически случается.

                                                                                                                                    И всё это решается Rust-ом просто на уровне правил языка. Получить UB сложно, получить нарушение strict aliasing вообще невозможно.


                                                                                                                                    Главная беда, С++, имхо абсолютно не работа с памятью (она вполне безопасна и комфортна после некоторого уровня понимания), а адски замороченный стандарт с «кучей условий мелким шрифтом, сносками и звёздочками», что как раз и демонстрирует пример этого поста…

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


                                                                                                                                    вся эта сложность сделана с единственной целью — позволить компилятору выжимать максимум возможной эффективности из кода.

                                                                                                                                    А вот это можно обозначить за главную проблему современного стандарта С++ :) На нём приходится писать так, чтобы удобно было компилятору, а не тебе. Не сказал бы, что в Rust нет такого (чего только стоит секс с borrow checker-ом зачастую), но если в Rust эти потуги вознаграждаются в итоге более строгой архитектурой и меньшим количеством хаков, то в С++ обычно выходит с точностью да наоборот)

                                                                                                                                      0
                                                                                                                                      Не интересно комментировать остальное, кроме вот этого:

                                                                                                                                      Тоже не скажу за всех, но Segmentation Fault на моей памяти самая частая причина почему падает плюсовое приложение.

                                                                                                                                      1. разных возможностей уронить процесс вообще не так уж и много, и неправильная работа с памятью — это самая широкая из них. Поэтому не удивительно, что программы с ошибками падают чаще всего именно на памяти. Ну не ud2 же им падать?

                                                                                                                                      2. любая безопасная работа требует чёткого понимания когда конкретно с чем конкретно работаем. Тогда пиши хоть на асме — не будет никаких проблем. Юниксы и прочие Линуксы, написанные на самых небезопасных С/С++ с годами аптайма тому пример (Винда диапазона NT4.0-2000-7 тоже совсем не так дурна на самом деле, как её любят представлять, и там точно микс С/С++ даже в kernel mode драйверах, но никсы в примере канонiчнее, конечно).

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

                                                                                                                                      Отсюда простой вывод — неча на зеркало пенять, коли рожа крива когда прозводительность любого минимально сложного решения на первом месте, то, в общем случае, альтернативы всё равно нет.
                                                                                                                                        0
                                                                                                                                        1. разных возможностей уронить процесс вообще не так уж и много, и неправильная работа с памятью — это самая широкая из них. Поэтому не удивительно, что программы с ошибками падают чаще всего именно на памяти. Ну не ud2 же им падать?

                                                                                                                                        Ну в сишарпе самая частая ошибка — падение с NullReferenceException. Вторая — KeyNotFoundException.


                                                                                                                                        1. любая безопасная работа требует чёткого понимания когда конкретно с чем конкретно работаем. Тогда пиши хоть на асме — не будет никаких проблем. Юниксы и прочие Линуксы, написанные на самых небезопасных С/С++ с годами аптайма тому пример (Винда диапазона NT4.0-2000-7 тоже совсем не так дурна на самом деле, как её любят представлять, и там точно микс С/С++ даже в kernel mode драйверах, но никсы в примере канонiчнее, конечно).

                                                                                                                                        Остается вопрос стоимости написания такого безопасного приложения. Один вопрос когда у вас сениоры с 10 годами опыта должны еще друг за дружкой следить и валгринды гонять на регрессе. И другое когда у вас джун с 1-2 годами опыта выдает продукт с теми же характеристиками.


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

                                                                                                                                        А вот это миф. Собственно, раст хороший пример, когда с безопасностью можно еще и выиграть в производительности. Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr. Безопасность и производительность абсолютно ортогональные вещи. То что в некоторых языках решают пожертововать одним ради другого не означает, что это основной закон мироздания.

                                                                                                                                          +1
                                                                                                                                          Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr.

                                                                                                                                          А зачем использовать shared_ptr там, где и в плюсах можно использовать ссылки?

                                                                                                                                            0

                                                                                                                                            Тем, что & проверит множественность владельцев, то что никто не мутирует в это время нашу ссылку, то что она указывает на живой объект и не инвалидируется, в общем вот это все. А с ссылками никаких гарантий нет.

                                                                                                                                              +1

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

                                                                                                                                                0

                                                                                                                                                Разве в расте можно продлить время жизни? Как я понимаю это просто защита от dangling reference.

                                                                                                                                                  0

                                                                                                                                                  Да, судя по примерам кода, которые PsyHaSTe тут приводит, он либо вообще не понимает, что такое reference, shared/unique_ptr, либо специально всех в заблуждение вводит.

                                                                                                                                            0
                                                                                                                                            Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr.

                                                                                                                                            сколько раз вам нужно написать что в плюсах «вместо растовых ссылок» используются ссылки, а не shared_ptr?
                                                                                                                                              0

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

                                                                                                                                                0
                                                                                                                                                Немного доставляют все эти речи о безопасном расте и стрельбе по ногам в C++.
                                                                                                                                                В C/C++ когда-то решили, что за корректность семантики тех или иных действий на той или иной конкретной платформе отвечает программист и назвали это неопределенным поведением. Решение оказалось удачным, что показывает объем реально работающего кода на этих языках.
                                                                                                                                                Прошло 40 где-то лет и в Rust на основании накопленного опыта придумали, как в C ограничить 3 вида UB в самом языке и еще несколько на уровне библиотеки и делать это во прямо во время компиляции, не дожидаясь рантайма. Смержили результат с OCaml'ом и презентовали публике. Как по мне — норм, пожалуй, лучше, чем то, что было. Хотя куча прелестей все-равно осталось.
                                                                                                                                                Но всерьез напирать на какую-то мифическую безопасность одного или, наоборот, опасность другого…
                                                                                                                                                  0

                                                                                                                                                  Для раста формально доказано, что в сейф подмножестве вы не получите УБ. Если вы доверяете ансейфу в стд (он сейчас тоже валидируется формально, к слову), то получается что уб в ваше программе невозможно получить. Равно как и разыменование нуллов, и прочие неприятные вещи. Как по мне весьма существенная гарантия.

                                                                                                                                                    0
                                                                                                                                                    Вы не получите конкретное и ограниченное подмножество UB. Да, это «доставучее» подмножество, но Rust явно перечисляет, что он не считает запрещенных UB. С моей точки зрения авторы языка прАвы, а вот апологеты не совсем.
                                                                                                                                                      0

                                                                                                                                                      Вы вообще не получите UB. Ни подмножества, ни надмножества. Без ансейф раста получить уб невозможно.

                                                                                                                                                        0
                                                                                                                                                        Еще раз: посмотрите внимательно растомикон. В безопасном расте вы не получите:
                                                                                                                                                        Dereferencing null, dangling, or unaligned pointers
                                                                                                                                                        Reading uninitialized memory
                                                                                                                                                        Breaking the pointer aliasing rules
                                                                                                                                                        Producing invalid primitive values:
                                                                                                                                                        dangling/null references
                                                                                                                                                        null fn pointers
                                                                                                                                                        a bool that isn't 0 or 1
                                                                                                                                                        an undefined enum discriminant
                                                                                                                                                        a char outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
                                                                                                                                                        A non-utf8 str
                                                                                                                                                        Unwinding into another language
                                                                                                                                                        Causing a data race

                                                                                                                                                        Это серьезный прогресс, но и не исчерпывающий список.
                                                                                                                                                          0

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

                                                                                                                                                          0
                                                                                                                                                          Ну, вообще-то можно, нопремер, при конверсиях из плавающей точки в int. Для борьбы с этим явлением сделали даже специальный ключик -Zsaturating-float-casts. Раньше (и сейчас без этого ключика, насколько я понимаю), можно было в safe code написать примерно следующее (сорян, я не растаман, простите очепятки):
                                                                                                                                                          let array_idx = 1e99999f64 as usize; // ой, не влезло, array_idx не определен
                                                                                                                                                          let val = some_array[array_idx]; // упс
                                                                                                                                                          

                                                                                                                                                          как-то так. Насколько я вижу, соответствующий issue до сих пор не закрыт.
                                                                                                                                                            0

                                                                                                                                                            Ну это ICE, тут вопрос другой. От багов компилятора ни один язык не защитит.

                                                                                                                                                              0

                                                                                                                                                              Не то чтобы это баг компилятора, просто обычный случай протекания абстракции. Перед конверсиями такого рода в общем случае требуются проверки, но на каждый чих их делать дорого, отсюда и вот эта раскоряка в лице этого флажка. Когда говорят "математически доказано", "проверено электроникой" и так далее, забывают, что математическое доказательство относится к МОДЕЛИ, а модели никогда не отражают суровую реальность идеально.

                                                                                                                                                                0

                                                                                                                                                                Попробовал проверить это локально, не ругается ли клиппи, но у меня даже собрать не вышло: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=b9d3bb21be0d1c2a5cfbc0a46749fb06


                                                                                                                                                                Когда говорят "математически доказано", "проверено электроникой" и так далее, забывают, что математическое доказательство относится к МОДЕЛИ, а модели никогда не отражают суровую реальность идеально.

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

                                                                                                                                                                  0
                                                                                                                                                                  Я там девяток слишком много нарисовал видимо, f64 столько не вмещает. Max double по-моему 1.7e+308 где-то. Когда я запускаю код в этом playground в release и debug, у индекса получаются разные значения, что как бы намекает, что как минимум одно из них мусорное, а, может, и оба.
                                                                                                                                                                    0
                                                                                                                                                                      0

                                                                                                                                                                      Я же говорю — это не бага, а неизбежное зло. В таких конверсиях компилятор либо должен вставить ряд runtime проверок и зарулить производительность в ряде сценариев в минуса, либо пойти по пути C/C++ и оставить добавление проверок в каждом конкретном случае на усмотрение программиста (сиречь допустить UB). Это цугцванг.

                                                                                                                                                                        0

                                                                                                                                                                        Достаточно запретить такую конверсию, пусть разраб либо сам через ансейф реализует нужное ему поведение, либо даже не знаю что сделать.


                                                                                                                                                                        Делать это UB смысла нет, потому что результатом все равно не получится воспользоваться.

                                                                                                                                                                          0

                                                                                                                                                                          Получится, если при такой конверсии float/double влезут в целевой целочисленный тип. Если разработчик уверен, что влезет — все нормально. Если не влезет — увы, будет печаль. Насчёт вынести это в unsafe — ну хз, выглядит, честно говоря, как недавняя попытка экопротестунов закрыть деревянными палетами дизельный генератор :)

                                                                                                                                                                            0

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


                                                                                                                                                                            В текущем виде каст смысла не имеет. Мало того что мы кастуем из флоата в инт в значение другой битности, так еще и значение не принадлежащее домену типа.

                                                                                                                                                                              0
                                                                                                                                                                              Почему не имеет смысла? Сама по себе операция вполне осмысленная — превращение числа с плавающей точкой в целочисленное число через отрезание дробной части. Не нравится что это делается через каст — ну назовите её как-то по-другому, скажем, trunc, это ровным счётом ничего не изменит — все так же либо нужна будет неявная проверка диапазона на каждый чих, что медленно, либо надо будет доверять программисту и предоставить ему решать, когда нужно выполнять проверку, а когда нет.
                                                                                                                                                                                0

                                                                                                                                                                                У меня в хаскеле есть минимум три функции с сигнатурой [которая после мономорфизации выглядит как] Double -> Int, называются floor, ceil и round. Какую из них надо выбрать под такой каст и почему?

                                                                                                                                                                                  0
                                                                                                                                                                                  Дело не в этом, а в необходимости проверки на то, что число помещается в целевой диапазон, при каждой операции, что по данным, приведённым в соответствующем issue, ведёт к серьёзной деградации производительности в ряде сценариев. Так-то — любую, при условии, что это будет документировано.
                                                                                                                                                    0
                                                                                                                                                    Сколько угодно. Получается там, где в расте будет безопасный код на плюсах имеем кучу потенциально стреляющего по ногам кода.

                                                                                                                                                    к черту «потенциально», давайте «фактически»
                                                                                                                                                      0

                                                                                                                                                      Окей, кучу фактически стреляющего по ногам кода.

                                                                                                                                                        0
                                                                                                                                                        Окей, кучу фактически стреляющего по ногам кода.
                                                                                                                                                        ну уж нет, не отделаетесь. Вы написали:
                                                                                                                                                        Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr

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

                                                                                                                                                          Ну вот давайте такой пример:


                                                                                                                                                          fn f<'a>(x: &'a i32) -> impl Fn() -> i32 + 'a {
                                                                                                                                                              move || *x
                                                                                                                                                          }
                                                                                                                                                          
                                                                                                                                                          fn main() {
                                                                                                                                                              let x = 5;
                                                                                                                                                              let y = f(&x);
                                                                                                                                                              println!("{}", y());
                                                                                                                                                          }

                                                                                                                                                          На плюсах:


                                                                                                                                                          #include <memory>
                                                                                                                                                          #include <iostream>
                                                                                                                                                          #include <functional>
                                                                                                                                                          
                                                                                                                                                          std::function<int(void)> f(std::shared_ptr<int> x) {
                                                                                                                                                              return [&]() { return *x; };
                                                                                                                                                          }
                                                                                                                                                          
                                                                                                                                                          int main() {
                                                                                                                                                              std::shared_ptr<int> x(std::make_shared<int>(4));
                                                                                                                                                              std::function<int(void)> y = f(x);
                                                                                                                                                              std::cout << y() << std::endl;
                                                                                                                                                          }

                                                                                                                                                          При этом даже шаред_птр не очень спасут, потому что вот это будет ошибкой компиляции:


                                                                                                                                                          fn f<'a>(x: &'a i32) -> impl Fn() -> i32 + 'a {
                                                                                                                                                              move || *x
                                                                                                                                                          }
                                                                                                                                                          
                                                                                                                                                          fn main() {
                                                                                                                                                              let y;
                                                                                                                                                              {
                                                                                                                                                                  let x = 4;
                                                                                                                                                                  y = f(&x);
                                                                                                                                                              }
                                                                                                                                                              println!("{}", y());
                                                                                                                                                          }

                                                                                                                                                          А вот это — нет:


                                                                                                                                                          std::function<int(void)> f(std::shared_ptr<int> x) {
                                                                                                                                                              return [&]() { return *x; };
                                                                                                                                                          }
                                                                                                                                                          
                                                                                                                                                          int main() {
                                                                                                                                                              std::function<int(void)> y(nullptr);
                                                                                                                                                              {
                                                                                                                                                                  std::shared_ptr<int> x(std::make_shared<int>(4));
                                                                                                                                                                  y = f(x);
                                                                                                                                                              }
                                                                                                                                                              std::cout << y() << std::endl;
                                                                                                                                                          }
                                                                                                                                                            0
                                                                                                                                                            На плюсах:
                                                                                                                                                            даже с std::shared_pt без UB не смогли, ок, пишите на расте от греха подальше. Но всякую чушь нести не надо ибо аналогом на плюсах будет:
                                                                                                                                                            #include <iostream>
                                                                                                                                                            #include <functional>
                                                                                                                                                            
                                                                                                                                                            auto f(int& x) {
                                                                                                                                                                return std::function([&] { return x; });
                                                                                                                                                            }
                                                                                                                                                            
                                                                                                                                                            int main() {
                                                                                                                                                                int x = 4;
                                                                                                                                                                auto y = f(x);
                                                                                                                                                                std::cout << y() << std::endl;
                                                                                                                                                            }
                                                                                                                                                            
                                                                                                                                                              +3
                                                                                                                                                              даже с std::shared_pt без UB не смогли

                                                                                                                                                              Так про это и речь, не?

                                                                                                                                                                –2
                                                                                                                                                                Если ты не можешь забить гвоздь в стену, а вместо этого попадаешь по пальцу, это не повод винить молоток. Это повод научиться забивать гвозди так, чтобы при этом не попадать по пальцам. Смотря на эти упражнения с захватом временных копий shared_ptr по ссылке, я где-то понимаю, откуда в растовских крейтах берутся эти десятки CVE.
                                                                                                                                                                  +3
                                                                                                                                                                  Если ты не можешь забить гвоздь в стену, а вместо этого попадаешь по пальцу, это не повод винить молоток.

                                                                                                                                                                  А ещё это повод сказать, что молоток уступает тому инструменту, за который невозможно взяться так, чтобы попасть по пальцам.

                                                                                                                                                                    0
                                                                                                                                                                    Если этот инструмент позволяет забивать гвозди только определенной марки и только под определенным углом, то какбе нельзя сказать что молоток ему прямо «уступает». Зависит от ситуации.
                                                                                                                                                                  –1
                                                                                                                                                                  Так про это и речь, не?
                                                                                                                                                                  во-первых, с него станется и специально эту багу посадить. Во-вторых, речь про другое. PsyHaSTe пытается доказать что в плюсах не существует способа добиться производительности rust. А способ есть, всегда, надо лишь головой думать, что и как ты делаешь. Если же хочется не думать, а клацать пока не соберется «корректная» программа, тогда да, раст безусловно лучше.
                                                                                                                                                                    0
                                                                                                                                                                    плюсах не существует способа добиться производительности rust

                                                                                                                                                                    Э, нет, не надо тут strawman использовать. Я сказал, что производительность и безопасность ортогональны, и не вам не всегда обязательно жертвовать одним в пользу другого.

                                                                                                                                                                    –1
                                                                                                                                                                    Так про это и речь, не?
                                                                                                                                                                    речь не про это. Коллега пытается доказать, что раст быстрее плюсов потому что на плюсах невозможно написать корректную программу не теряя в производительности. Это ложь, а (личная) некомпетентность не является аргументом в пользу невозможности.
                                                                                                                                                                    0

                                                                                                                                                                    Ну так это ведь не совсем аналог, если я так понимаю пере выводом написать x = 5 то выведется совсем не то.


                                                                                                                                                                    Проверить, к сожалению, не могу, потому что ваш пример у меня не компилируется: https://rextester.com/XRE91350


                                                                                                                                                                    пишите на расте от греха подальше

                                                                                                                                                                    Так я и сделаю.

                                                                                                                                                                      0
                                                                                                                                                                      Э, нет, не надо тут strawman использовать. Я сказал, что производительность и безопасность ортогональны, и не вам не всегда обязательно жертвовать одним в пользу другого.
                                                                                                                                                                      нет, вы сказали:
                                                                                                                                                                      Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr.
                                                                                                                                                                      что я собственно и прошу доказать.
                                                                                                                                                                      Ну так это ведь не совсем аналог, если я так понимаю пере выводом написать x = 5 то выведется совсем не то.

                                                                                                                                                                      Проверить, к сожалению, не могу, потому что ваш пример у меня не компилируется: rextester.com/XRE91350
                                                                                                                                                                      мой пример отлично компилируется актуальной версией компилятора и стандарта. А вот «написать перед выводом x = 5» в расте не получится, из-за заимствования. Зачем вы спорите о языках ни в одном из которых вы не компетентны?
                                                                                                                                                                        0
                                                                                                                                                                        что я собственно и прошу доказать.

                                                                                                                                                                        Я показал по крайней мере один пример. Этого достаточно для утверждения, что бесплатная безопасность — бывает.


                                                                                                                                                                        мой пример отлично компилируется актуальной версией компилятора и стандарта. А вот «написать перед выводом x = 5» в расте не получится, из-за заимствования. Зачем вы спорите о языках ни в одном из которых вы не компетентны?

                                                                                                                                                                        Я прекрасно знаю, что оно не компилируется. Примерно то же поведение я хотел бы в плюсах. Если не ошибку компиляции, то хотя бы эксепшн в рантайме.

                                                                                                                                                                          0
                                                                                                                                                                          Я показал по крайней мере один пример.
                                                                                                                                                                          этот пример, даже будь он написан без ошибок, абсолютно ничего не доказывает
                                                                                                                                                                          Этого достаточно для утверждения, что бесплатная безопасность — бывает.
                                                                                                                                                                          я просил доказать не это. Я просил привести пример кода на расте, не выразимого в плюсах без доп. накладных расходов. Этого вы сделать не можете и даже не понимаете почему.
                                                                                                                                                                          Я прекрасно знаю, что оно не компилируется. Примерно то же поведение я хотел бы в плюсах. Если не ошибку компиляции, то хотя бы эксепшн в рантайме.
                                                                                                                                                                          так а если я хочу поменять значение переменной на которую существует ссылка? Использовать «весьма небесплатные» reference-counted обертки над ссылками?
                                                                                                                                                                            0
                                                                                                                                                                            я просил доказать не это. Я просил привести пример кода на расте, не выразимого в плюсах без доп. накладных расходов. Этого вы сделать не можете и даже не понимаете почему.

                                                                                                                                                                            Я уже показал. Либо вы будете делать обертки, которые проверят это, либо потеряете в безопасности.


                                                                                                                                                                            Другой пример — Option<NonZero<u32>> какой-нибудь.


                                                                                                                                                                            так а если я хочу поменять значение переменной на которую существует ссылка? Использовать «весьма небесплатные» reference-counted обертки над ссылками?

                                                                                                                                                                            Значит придется перехотеть и выразить свои мысли иначе. А то напоминает, как товарищь eao спрашивал "а как мне достать значение из опшна без проверки, если ну очень надо".

                                                                                                                                                                              0
                                                                                                                                                                              Я уже показал. Либо вы будете делать обертки, которые проверят это, либо потеряете в безопасности.
                                                                                                                                                                              а. ваше утверждение было не про безопасность
                                                                                                                                                                              б. если не думать головой что ты делаешь никаких оберток не напасешься
                                                                                                                                                                              Другой пример — Option&ltNonZero&ltu32&gt&gt какой-нибудь.
                                                                                                                                                                              Написать его аналог на плюсах несложно. Но никто не пишет… наверно потому, что не нужен?
                                                                                                                                                                              Значит придется перехотеть и выразить свои мысли иначе
                                                                                                                                                                              например?
                                                                                                                                                                              А то напоминает, как товарищь eao спрашивал «а как мне достать значение из опшна без проверки, если ну очень надо».
                                                                                                                                                                              а если я могу доказать что в этой ветке кода вышеупомянутый опшн никогда не будет пустым, зачем мне его перепроверять? Или так работает та самая zero cost безопасность которую вы пытаетесь доказать? Пока что только опровергаете
                                                                                                                                                                                0
                                                                                                                                                                                а. ваше утверждение было не про безопасность

                                                                                                                                                                                То есть в фразе "производительность и безопасность ортогональны, и не вам не всегда обязательно жертвовать одним в пользу другого" нет ничего про безопасность? Ясно-понятно.


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

                                                                                                                                                                                Верно, но чем меньше нужно про это думать, тем лучше.


                                                                                                                                                                                Написать его аналог на плюсах несложно. Но никто не пишет… наверно потому, что не нужен?

                                                                                                                                                                                Зиро-кост абстракцию такого вида без поддержки компилятора вы не напишете. А если мы затащим таким образом одну, вторую, третью фичи раста получим раст. Тогда что от плюсов останется?
                                                                                                                                                                                А то, что нинужна — ну конечно, настоящий программист же всегда помнит, где у него что на нулл проверилось и в каком поле нолик означает отсутствие значение, а в каком — нет.


                                                                                                                                                                                например?

                                                                                                                                                                                Попытка модифицировать значение на которое кто-то держит ссылку — это ошибка. Можно сделать арены, чтобы ссылок не было, можно убрать мутабельность, вариантов много.


                                                                                                                                                                                а если я могу доказать что в этой ветке кода вышеупомянутый опшн никогда не будет пустым, зачем мне его перепроверять? Или так работает та самая zero cost безопасность которую вы пытаетесь доказать? Пока что только опровергаете

                                                                                                                                                                                Ну так вот пусть компилятор доказывает. А "мамай клянус" утверждениям я не верю.

                                                                                                                                                                                  0
                                                                                                                                                                                  То есть в фразе «производительность и безопасность ортогональны, и не вам не всегда обязательно жертвовать одним в пользу другого» нет ничего про безопасность? Ясно-понятно.
                                                                                                                                                                                  сколько раз мне надо тыкать вас в вашу же цитату «Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr.» прежде чем вы признаете что облажались?
                                                                                                                                                                                  Зиро-кост абстракцию такого вида без поддержки компилятора вы не напишете
                                                                                                                                                                                  да ладно? Вот прям невозможно написать?
                                                                                                                                                                                  Попытка модифицировать значение на которое кто-то держит ссылку — это ошибка
                                                                                                                                                                                  Но это не ошибка.
                                                                                                                                                                                  Можно сделать арены, чтобы ссылок не было, можно убрать мутабельность, вариантов много.
                                                                                                                                                                                  я хочу писать простой, понятный и производительный код, а не плясать по прихоти компилятора
                                                                                                                                                                                  Ну так вот пусть компилятор доказывает
                                                                                                                                                                                  ценой стоимости в рантайме? Тогда ваше утверждение «Безопасность и производительность абсолютно ортогональные вещи» — ЛПП.
                                                                                                                                                                                    0
                                                                                                                                                                                    сколько раз мне надо тыкать вас в вашу же цитату «Наглядный пример — бесплатные ссылки & вместо вполне себе платных shared_ptr.» прежде чем вы признаете что облажались?

                                                                                                                                                                                    shared_ptr используется вместо сразу трех вещей, которые есть в раст: &, Rc и Arc. А теперь посмотрите, какая относительная частоат их использования в среденй растопрограмме. Понятное дело, что когда вам надо в рантайме считать ссылки то & не подойдет. По почти всегда можно посчитать всё статически.


                                                                                                                                                                                    да ладно? Вот прям невозможно написать?

                                                                                                                                                                                    Я так подумал, что вполне напишете. Ок, это я не то сказал.


                                                                                                                                                                                    Но это не ошибка.

                                                                                                                                                                                    Вот я бы очень расстроился, если бы мне кто-то дал ссылку а потом начал по ней что-то менять.


                                                                                                                                                                                    я хочу писать простой, понятный и производительный код, а не плясать по прихоти компилятора

                                                                                                                                                                                    Ну это тогда вам в питон. А то в С++ злой компилятор тоже не разрешит вместо числа строчку передать.


                                                                                                                                                                                    ценой стоимости в рантайме? Тогда ваше утверждение «Безопасность и производительность абсолютно ортогональные вещи» — ЛПП.

                                                                                                                                                                                    То что компилятор проверил в рантайме не нужно, потому что все уже проверено.

                                                                                                                                                                                      0
                                                                                                                                                                                      Вот я бы очень расстроился, если бы мне кто-то дал ссылку а потом начал по ней что-то менять.

                                                                                                                                                                                      Вы же шарповик, если не ошибаюсь? А почему вы в C# не расстраиваетесь, когда меняется содержимое каких-то объектов, ссылки на которые у вас есть? Там же практически все объекты только по ссылке и доступны, кроме примитивных типов.
                                                                                                                                                                                        0

                                                                                                                                                                                        Весьма обижаюсь. Поэтому делаю только гет-онли интерфейсы и достаточно активно юзаю System.Collections.Immutable.

                                                                                                                                                                                          0
                                                                                                                                                                                          Сильно сомневаюсь, что это вам сильно помогает :) Вы, видимо, должны расстраиваться постоянно, потому что любой, я там не знаю, экземпляр NetworkStream будет менять свое состояние, пока вы держите на него ссылку, и вообще большинство классов из .Net Framework, у которых есть хоть какая-то внутренняя логика, будут себя так вести.
                                                                                                                                                                                            0

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




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

                                                                                                                                                                                              0
                                                                                                                                                                                              Это — не нормально, а вот когда тот же вышеупомянутый NetworkStream меняет свое состояние, пока вы держите на него ссылку, это совершенно нормально, более того — так он и работает. Понятия нормальности и ненормальности сильно зависят от конкретной ситуации.
                                                                                                                                                                                                0

                                                                                                                                                                                                Ну а в расте это называется interior mutability и точно так же разрешена) А вот внешняя мутабельность — с ограничениями борровчекера. Вроде звучит логично.

                                                                                                                                                                                                  0
                                                                                                                                                                                                  Какой же это interior mutability, если этот NetworkStream постоянно дергает за ниточки третья сторона — ОС посредством оперирования состоянием его сокета? :) Да и честно говоря другим частям вашей же программы, которым вы передали копию ссылки (скажем, каким-то обработчикам событий), ничего не мешает выполнять из этого потока чтение, запись, менять настройки сокета и так далее?
                                                                                                                                                                                                    0
                                                                                                                                                                                                    Какой же это interior mutability, если этот NetworkStream постоянно дергает за ниточки третья сторона — ОС посредством оперирования состоянием его сокета? :)

                                                                                                                                                                                                    Именно такая. Объект мутируется, хотя вам кажется, что нет.


                                                                                                                                                                                                    А вообще проблема с тем, что &mut означает не то, что можно было бы подумать. Тут неплохо объясняется.

                                                                                                                                                                                                      0

                                                                                                                                                                                                      Ну как же "мне кажется, что нет", когда я знаю, что он мутируется, на этом, собственно, вся логика ра