Команда Rust рада сообщить о выпуске новой версии, 1.40.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.


Если вы установили предыдущую версию Rust средствами rustup, то для обновления до версии 1.40.0 вам достаточно выполнить следующую команду:


$ rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.


Что вошло в стабильную версию 1.40.0


Основными новшествами являются введение атрибута #[non_exhaustive], улучшения macros!() и #[attribute]. Наконец, миграционные предупреждения анализатора заимствований стали ошибками в Rust 2015. Смотрите подробности выпуска для дополнительной информации.


#[non_exhaustive] структуры, перечисления и варианты перечислений


Предположим, вы являетесь автором библиотеки alpha, которая содержит pub struct Foo. Вы хотели бы сделать поля структуры alpha::Foo публичными, но не уверены, придётся ли вам в будущих выпусках добавить больше полей в Foo. Возникает дилемма: либо вы делаете поля приватными с последующими неудобствами, либо вы рискуете поставить пользователей в зависимость от полей и потом нарушит их код при добавлении новых. В Rust 1.40.0 представлен способ решить проблему с помощью #[non_exhaustive].


Атрибут #[non_exhaustive] прикрепляется к структуре или варианту перечисления и препятствует полному сопоставлению полей, созданию упомянутой структуры или варианта вне крейта с их объявлением. Следующий пример демонстрирует ошибки в крейте beta, зависящего от alpha:


// alpha/lib.rs:

#[non_exhaustive]
struct Foo {
    pub a: bool,
}

enum Bar {
    #[non_exhaustive]
    Variant { b: u8 }
}

fn make_foo() -> Foo { ... }
fn make_bar() -> Bar { ... }

// beta/lib.rs:

let x = Foo { a: true }; //~ ОШИБКА
let Foo { a } = make_foo(); //~ ОШИБКА
let Foo { a, .. } = make_foo(); //~ OK
          // -- `beta` все еще будет компилироваться при добавлении полей.

let x = Bar::Variant { a: 42 }; //~ ОШИБКА
let Bar::Variant { b } = make_bar(); //~ ОШИБКА
let Bar::Variant { b, .. } = make_bar(); //~ OK
                   // -- `beta` все еще будет компилироваться...

Что же происходит за кулисами? Видимость конструкторов для #[non_exhaustive] структуры или варианта перечисления будет понижена до pub(crate), тем самым запрещая их использование в сторонних крейтах.


Возможно, что более важным аспектом #[non_exhaustive] является то, что атрибут может быть прикреплён к самим перечислениям. Вот код, взятый из std::cmp::Ordering:


#[non_exhaustive]
pub enum Ordering { Relaxed, Release, Acquire, AcqRel, SeqCst }

В данном случае #[non_exhaustive] гарантирует возможность добавления новых вариантов в будущем. Это достигается запретом другим пакетам к использованию исчерпывающего сопоставления с образом для Ordering. Компилятор бы отклонил следующее:


match ordering {
    Relaxed | Release | Acquire | AcqRel | SeqCst => { /* logic */ }
    //~^ ОШИБКА; если новый вариант был бы добавлен,
    // это сломалось бы, если ошибки не было бы с самого начала.
}

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


match ordering {
    Relaxed | Release | Acquire | AcqRel | SeqCst => { /* logic */ }
    _ => { /* logic */ } // OK; если будут добавлены новые варианты, ничего не сломается.
}

Подробная информация об атрибуте #[non_exhaustive] доступна в отчёте о стабилизации.


Улучшения макросов и атрибутов


В 1.40.0 мы внесли несколько улучшений в макросы и атрибуты, включая:



Миграционные предупреждения анализатора заимствований становятся ошибками в редакции Rust 2015


В выпуске 1.35.0 мы сообщили, что NLL появился в редакции Rust 2015 после первого выпуска для 2018 редакции в Rust 1.31.


Как мы сказали, старый анализатор заимствований мог допустить небезопасное управление памятью, и с помощью нового анализатора (NLL borrow checker) эти недочёты были решены. Так как эти ошибки могли нарушить работу стабильного кода, мы решили постепенно вводить эти ошибки, проверяя разрешит ли сборку программы старый анализатор, и запретит ли её новый. В этих случаях ошибки заменялись предупреждениями.


Предыдущий выпуск Rust 1.39.0 заменил эти предупреждения на ошибки для кода с 2018 редакцией. Rust 1.40.0 применит те же самые изменения для кода 2015 редакции, навсегда закрывая эти дыры в безопасности. Вместе с этим компилятор даже почистили от старого кода!


Если ваш проект не собирается из-за вышеописанных изменений, или вы хотите узнать больше, читайте пост Niko Matsakis's.


Больше константных функций в стандартной библиотеке


Начиная с Rust 1.40.0, следующая функция помечена как константная (const fn):



Стабилизированные функции в стандартной библиотеке


В Rust 1.40.0 были стабилизированы следующие функции и макросы:



Другие изменения


Синтаксис, пакетный менеджер Cargo и анализатор Clippy также претерпели некоторые изменения.


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


Участники 1.40.0


Множество людей собрались вместе, чтобы создать Rust 1.40.0. Мы не смогли бы сделать это без всех вас, спасибо!


От переводчиков


С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов.


Данную статью совместными усилиями перевели andreevlex, blandger, funkill, Hippolot, P0lunin, PsyHaSTe и LooMaclin.

Комментарии (56)


  1. Gorthauer87
    21.12.2019 11:56

    Вообще non_exhaustive легко делается при помощи unit поля в структуре или варианта в енаме. Хотя в последнем случае это плохо тем что он виден.
    Видел я плач ярославны на реддите, что это якобы плохая фича.


    1. PsyHaSTe
      21.12.2019 17:50
      +2

      Ну мое мнение что фича действительно не очень. Раньше если мы получали при добавлении варианта ошибку компиляции, то теперь мы обязаны написать еще одну ветку в матче. Которая (вангую) в 99% будет либо паникой либо молчаливым проглатыванием варианта с возвратом какого-то дефолта.


      В некотором смысле фича абсолютно противоположена философии раста.


    1. DarkEld3r
      22.12.2019 23:08

      Я тоже с этой фичей не сразу смирился, ещё в описании релиза приводят atomic::Ordering — да, мало какой "пользовательский" код будет этот enum матчить, но я плохо представляю какую логику можно воткнуть в _. Ну кроме паники, что несколько портит всю идею. Лучше бы про io::ErrorKind сказали.


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


  1. epishman
    21.12.2019 16:30

    Черт, смотрю я на Rust, он становится все сложнее и сложнее, и возникает вопрос — может дешевле работать на сырых указателях C++ (просто аккуратно) а для больших приложений взять какую-нибудь Scala? Я люблю Rust, но его zero cost совсем небесплатен для мозга программиста…


    1. mezastel
      21.12.2019 17:54
      +3

      Мне кажется что все равно в текущей модели, уровень когнитивных нагрузок совсем другой. Сейчас комфортно пользоваться всеми прелестями С++ можно только если ты уже программируешь лет 15-20 и научился обходить все подводные камни. Или же можно писать используя где-то 3-5% языка С++ (или даже регрессировать на С) и в принципе все будет более менее, особенно если ты делаешь что-то приземленное вроде numerical computing. Если нужен «кровавый enterprise» то конечно можно взять или C# или Kotlin, им Rust не конкурент и не пытается им быть.


      1. epishman
        21.12.2019 18:11

        Это да. Я не спец по C++, возможно более свежий Rust снимает часть подводных камней, но если нужно что-то быстрое и на коленке — то действительно С предпочтительней.


        1. freecoder_xx
          21.12.2019 19:25
          +1

          Ну вы просто знаете C и имеете опыт программирования на нем, но не знаете Rust и не имеете опыта программирования на нем. Конечно, в таком случае для вас С предпочтительней. А вот для меня — наоборот ) Я программировал и на том, и на другом, и Раст для меня предпочтительнее, особенно если нужно что-то "быстрое и на коленке", как ни странно.


      1. freecoder_xx
        21.12.2019 19:14
        +2

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


        1. epishman
          21.12.2019 19:49
          -1

          А, спор религиозный, пока кажется что джава доживает последние годы, просто неприлично уже в 21 веке тип переменной указывать впереди имени, а будущее за каким-нибудь скала-хаскель-#, или вдруг в Rust завезут до-нотацию, и он всех победит, все-таки концепция владения наиболее близка концепции неизменяемости, а писать в процедурном стиле Rc<RefCell<> это так себе удовольствие.


          1. freecoder_xx
            21.12.2019 21:10

            Почему же сразу религиозный? Я вроде бы вполне рациональные доводы привел. Может быть вы недостаточно повидали «кровавого enterprise» и не в курсе, чем он болен и каково лекарство )


            1. epishman
              21.12.2019 21:16

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


              1. freecoder_xx
                21.12.2019 21:34

                Лучшая типобезопасность — вот причина, почему Kotlin зашел. У Scala тоже был шанс, но она сама в себе запуталась, оказалась слишком сложной.


                1. epishman
                  21.12.2019 21:50

                  Забавно, прямо сейчас зашел на HH — вакансий Kotlin в названии — 106 (большинство либо андроид либо спринг), а Scala — 131 (практически все бэк). Может тренды уже поменялись, а мы не в курсе?


        1. Hippolot
          21.12.2019 20:24

          Rust не претендует на место Java, т.к. приходится бизнес-логику мешать со всякими RefCell, Arc, Rc, Box, что крайне неудобно.


          1. freecoder_xx
            21.12.2019 21:27
            +1

            Ну и что? Почему вы решили, что это вообще составляет проблему? )


            Я вот работал с несколькими крупными веб-приложениями, написанными на Rust, и в них Box и RefCell практически не использовались совсем (!), а там, где все-таки использовались — в единичных местах — никаких проблем и затруднений они не вызывали. Что же касается Arc и Mutex — так это вообще благо, ибо КОРРЕКТНЫЙ многопоточный код на Rust пишется в разы проще, чем на Java.


            Я часто слышу, как люди, которые особого опыта-то и не имеют в enterprise, пытаются априори отгородить его от Rust. Зачем вы это делаете? Я использую Rust в проектах enterprise-уровня и доволен. Не доволен пока только слабо развитой экосистемой, но к самому языку претензий нет. Тот уровень выразительности и безопасности для кодирования бизнесс-логики, который обеспечивает система типов Rust, с лихвой окупает небольшие неприятности, связанные с эпизодической ручной работой с умными указателями. И то, часто появление таких проблем — это свидетельство того, что нужно остановиться и подумать над общей архитектурой хранения данных и об ответственности за владение объектами в системе.


            1. epishman
              21.12.2019 21:52

              и в них Box и RefCell практически не использовались совсем
              Ну то есть иммутабельность и копирование — архитектурные принципы совсем другие нужны?


              1. freecoder_xx
                22.12.2019 20:20

                Обычно структуры используются не сильно большие, чтобы их упаковывать, чаще всего они — Copy-типы. Ну а коллекции — в них упаковка скрыта от пользователя. RefCell же полезен в связке с Rc, а когда у вас шаренных объектов и так мало, то еще меньшему числу нужна шаренная мутабельность. )


            1. Hippolot
              21.12.2019 21:55
              -2

              Эмм… И что? Почему вы решили, что это вообще составляет проблему?

              Потому что это привносит дополнительные неудобства! Концепцию лайфтаймов можно сборщиком мусора полностью убрать, что прикладные языки и делают, иначе приходится пользоваться умными указателями Arc и т.д. в некоторых случаях, которые не так уж и редко случаются. Например, создаёте вы N потоков в функции и передаёте им данные по ссылке, которыми владеет эта функция, а потом .join() в конце той же функции этих потоков, тогда придётся в Arc оборачиваеть/использовать scoped threads. В языке с GC такой проблемы бы не возникло вообще.


              Что же касается Arc и Mutex — так это вообще благо, ибо КОРРЕКТНЫЙ многопоточный код на Rust пишется в разы проще, чем на Java.

              Он пишется проще из-за правила "На один объект в один момент времени не могут указывать две изменяемые ссылки" и нормальной иерархической изменяемости, а Arc — это продление времени жизни объекта, что сборщик мусора сам по себе делает. Мьютекс бы забирал себе изменяемую ссылку, которая по определению GC живёт столько, сколько на неё указывают, и передавали бы просто Mutex<T>, а не Arc<Mutex<T>>. Концепция владения тоже, ИМХО, ненужна в языке для прикладных задач.


              Я часто слышу, как люди, которые особого опыта-то и не имеют в enterprise, пытаются априори отгородить его от Rust. Зачем вы это делаете?

              Я пишу ентерпрайз на Java, и в очень многих местах он объективно удобнее Rust. ИМХО, идеальный прикладной язык — это ООП язык с GC и возможностями формальной верификации программ системой типов как в Idris. Тогда было бы очень годно.


              1. freecoder_xx
                22.12.2019 20:44

                это ООП язык с GC и возможностями формальной верификации программ системой типов как в Idris

                Фигасе вы загнули ) Вряд ли возможна система типов "как в Idris", совместимая с ООП.


                Ну, ваш взгляд имеет право на существование. Но я подозреваю, что вы либо мало работали с Rust и он вам просто непривычен, либо какой-то неправильный энтерпрайз у вас был на Java ) Без ада с NPE.


                Концепция владения тоже, ИМХО, ненужна в языке для прикладных задач.

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


                В языке с GC такой проблемы бы не возникло вообще.

                В итоге там возникла бы другая проблема — гонка данных. Так что эта простота оказывает медвежью услугу: она создает видимость, что можно вот так просто взять и расшарить объект между потоками, не задумываясь о владении. Поэтому в той же Java многопоточное программирование — это совсем отдельное минное поле, требующее специальной подготовки джависта. А в Rust это вписывается очень органично — разок напрягся в самом начале, и дальше просто переиспользуешь уже имеющийся опыт )


                1. Hirrolot
                  22.12.2019 20:59

                  Фигасе вы загнули ) Вряд ли возможна система типов "как в Idris", совместимая с ООП.

                  Смотря что под ООП понимать, и что под ФП. У всех ведь разные определения в голове на этот счёт)


                  Ну, ваш взгляд имеет право на существование. Но я подозреваю, что вы либо мало работали с Rust и он вам просто непривычен, либо какой-то неправильный энтерпрайз у вас был на Java ) Без ада с NPE.

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


                  В итоге там возникла бы другая проблема — гонка данных.

                  Я не вижу гонки данных в моём примере, ведь мы делим лишь неизменяемые данные между потоками. Если такое же правило применить, как и в Rust (две изменяемые ссылки в одно и то же время нельзя), то и гонок данных можно избежать.


                  1. freecoder_xx
                    22.12.2019 21:03

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


                    1. Hirrolot
                      22.12.2019 21:07

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


                      1. mayorovp
                        23.12.2019 07:06
                        +1

                        А как вы можете быть в этом уверены?


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


                        1. Hirrolot
                          23.12.2019 07:48

                          Потому что в C# неизменяемость кастрированная:


                          using System;
                          
                          public class Test
                          {
                              class A {
                                  public int a;
                              }
                          
                              class B {
                                  public readonly A obj = new A();
                              }
                          
                              public static void Main()
                              {
                                  B b = new B();
                                  b.obj.a = 34;
                              }
                          }

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


                          1. mayorovp
                            23.12.2019 08:49
                            +1

                            Что-то я не увидел в ваших сообщениях выше языков с иерархической неизменяемостью… Надеюсь, это вы не про Java так сказали?


                            1. Hirrolot
                              23.12.2019 09:03

                              Он пишется проще из-за правила "На один объект в один момент времени не могут указывать две изменяемые ссылки" и нормальной иерархической изменяемости...

                              Конечно нет, я про Rust.


                              1. mayorovp
                                23.12.2019 09:09
                                +1

                                Ну так я вам и объясняю почему на Rust многопоточный код писать проще.


                  1. 0xd34df00d
                    23.12.2019 16:52

                    Смотря что под ООП понимать, и что под ФП. У всех ведь разные определения в голове на этот счёт)

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


                    1. EvgeniiR
                      23.12.2019 17:22

                      Смотря что под ООП понимать, и что под ФП. У всех ведь разные определения в голове на этот счёт)

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

                      Есть такие понимания, в которых не важно. Более того, оно не было важно в изначальной трактовке термина от Алана Кея(если уж занудствовать).
                      (Поэтому я за то чтобы выкинуть термин ООП за неоднозначность и взять что-нибудь конкретное и не дискредетировавшее себя).


                      1. PsyHaSTe
                        24.12.2019 00:07

                        Я склоняюсь в определению "ООП это как в Java".


                        А ООП по Кею в наши дни называется "акторная модель".


                        1. EvgeniiR
                          24.12.2019 08:25
                          -1

                          Я склоняюсь в определению «ООП это как в Java».

                          А что значит «как в Java»? В Java, много чего есть.

                          Если про «3 Кита» — ну, ничего хорошего скрывающегося под этим определением я не видел. Мало этого что-бы внятную разницу иметь между процедурным програмированием и ООП.
                          Без наследования, которое выше обсуждалось, жить точно можно и думаю лучше чем с ним, при удобной композиции, делегатах и т.п.

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


            1. Hirrolot
              23.12.2019 14:37

              в них Box и RefCell практически не использовались совсем (!), а там, где все-таки использовались — в единичных местах — никаких проблем и затруднений они не вызывали.

              Только что из actix-web подсмотрел:


    1. PsyHaSTe
      21.12.2019 17:54
      +2

      Черт, смотрю я на Rust, он становится все сложнее и сложнее

      Давайте посмотрим на этот выпуск — что поменялось? Переименовали unimplemented -> todo, ок. Добавили новый атрибут в стд — ок. Функционал который задперикейтили год назад и сыпали варнингами теперь окончательно выпилили — ок. Ну и пачку тривиальных функций добавили.


      Вы видите в этом особое усложнение?


      может дешевле работать на сырых указателях C++ (просто аккуратно) а для больших приложений взять какую-нибудь Scala?

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


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


      1. freecoder_xx
        21.12.2019 19:33

        Скала сильно переусложнена ИМХО, Раст там и рядом не стоял в аспекте "когнитивной нагрузки", которую зачастую требует скалистый код.


        1. PsyHaSTe
          21.12.2019 23:08
          +1

          Скала сложнее только если смотреть на плотность информации на строчку кода. Если смотреть в абсолютных величинах, то она получается попроще.


          Вторая проблема — неидиоматичность. Неидиоматичный раст написать тяжело потому что в половине случаев такой код просто не соберется, и придется спрашивать у сообщества как делать, в половине соберется, но придет клиппи и скажет как заменить. В скале же если не получается сделать правильно можно налепить что-то в стиле "Беттер джавы" и получить все те же проблемы, но только теперь со странным синтаксисом.




          Насчет типов — раст намного лучше мейнстрим языков, но все же ощутимо уступает более продвинутым системам. Тот же многопоток который одна из киллер фич раста писать на STM на порядок проще и приятнее, чем обмазываться арками и мьютексами. Если можно себе позволить гц и вам не жалко 50-100% производительности и x2-x10 памяти, то можно брать языки с более сильными системами типов и гц.


          1. 0xd34df00d
            22.12.2019 05:47

            Скала сложнее только если смотреть на плотность информации на строчку кода. Если смотреть в абсолютных величинах, то она получается попроще.

            Как хаскелист говорю, что скала переусложнена (и вообще в uncanny valley).


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


            1. PsyHaSTe
              22.12.2019 12:00

              Как хаскелист говорю, что скала переусложнена (и вообще в uncanny valley).

              1. Есть мнение, что в скале синтаксис попроще будет хаскелля. Если тупо сравнить количество синтаксических конструкций и сложность написания парсера
              2. Скала интересна тем что это жвм, эрго 100 миллионов библиотек на любой вкус. На хаскелле — чуть в сторону от проторенной тропинки и всё.

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


              1. epishman
                22.12.2019 17:51

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


                1. PsyHaSTe
                  22.12.2019 18:25

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


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


              1. 0xd34df00d
                23.12.2019 17:03

                Есть мнение, что в скале синтаксис попроще будет хаскелля.

                Лично у меня от этого бесконечного [_] рябит в глазах и начинает болеть голова.


                Если тупо сравнить количество синтаксических конструкций и сложность написания парсера

                Ну вот, например, описание всех возможных экспрешонов: http://hackage.haskell.org/package/template-haskell-2.15.0.0/docs/Language-Haskell-TH-Syntax.html#t:Exp, включая некоторые расширения. А как бы оно выглядело для скалы?


                Скала интересна тем что это жвм, эрго 100 миллионов библиотек на любой вкус.

                А как, кстати, ненативные и неидиоматичные для скалы библиотеки в ней ощущаются? Удобно ли с ними работать?


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

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


                1. PsyHaSTe
                  24.12.2019 00:11

                  Лично у меня от этого бесконечного [_] рябит в глазах и начинает болеть голова.

                  Ну, ML синтаксис вроде поприятнее выглядит, тут ничего не скажешь


                  Ну вот, например, описание всех возможных экспрешонов: http://hackage.haskell.org/package/template-haskell-2.15.0.0/docs/Language-Haskell-TH-Syntax.html#t:Exp, включая некоторые расширения. А как бы оно выглядело для скалы?

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


                  А как, кстати, ненативные и неидиоматичные для скалы библиотеки в ней ощущаются? Удобно ли с ними работать?

                  Не очень, но удобнее чем писать их самому.


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

                  Ну вот например:


                  https://scastie.scala-lang.org/bR8NNUdQS5a2fen1T8LVFw


                  На FPure были неплохие доклады про успехи на этом поприще, впрочем я думаю вы про проекции Футамуры и так в курсе. Ну и там же всякие штуки про автоматическую оптимизацию наивной функции let y = sqr(x, 5) в let xx = x*x; let y = xx*xx*x


        1. PsyHaSTe
          22.12.2019 00:20

          Как вам такая когнитивная нагрузка?



          И нет, в скале даже близко так сложно бы не вышло.


          1. epishman
            22.12.2019 19:18

            Я думал, что уж если переписывать в императивном стиле через .await, тогда не должно быть .then(), стримы тоже разложить в циклы, это разве не упростит пример, сразу будут видны блоки, области видимости и т.д.?


            1. PsyHaSTe
              22.12.2019 20:41

              В данном примере асинк-авейт по некоторым причинам нельзя использовать (он еще не со всем хорошо работает), поэтому вот так.


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




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


              1. freecoder_xx
                22.12.2019 20:51

                Так ведь спор пока и идет насчет ширины этого отверстия.


                1. PsyHaSTe
                  22.12.2019 21:09

                  Цепляться к неточностям аналогии — плохой способ вести диалог.


                  Я уверяю, что если у меня не будет ограничений на производительность (скажем, меня устроит производительность уровня Java), то на Scala/Haskell я напишу более безопасное и масштабируемое решение, и за меньший срок.


          1. freecoder_xx
            22.12.2019 20:58

            Когда сообщения об ошибках разрывают поток кода — совершенно невозможно ничего понять (тому кто видит этот код впервые). Так что да, в таком оформлении — нагрузка высока. Но лично я так не программирую на Rust.


    1. Cerberuser
      21.12.2019 18:09
      +3

      Я люблю Rust, но его zero cost совсем небесплатен для мозга программиста…

      ИМХО, "просто аккуратно" пользоваться C++ — вещь ещё более "небесплатная".


    1. freecoder_xx
      21.12.2019 19:17

      Эмм… Я вот программирую на Расте каждый день и уже устаю ждать некоторых фич, которые очень хочется иметь в языке и которые все пилятся и пилятся. Где вы увидели усложнение языка? Кроме async/await в последнее время вообще небыло никаких принципиальных нововведений.


      1. Hippolot
        21.12.2019 20:20
        +1

        Pin


        1. snuk182
          22.12.2019 01:53

          Узкая ниша для неперемещаемых в рантайме данных.


          1. PsyHaSTe
            22.12.2019 12:24
            -1

            Любой асинк код — это не узкая ниша.


            1. snuk182
              22.12.2019 14:09

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


              1. PsyHaSTe
                22.12.2019 14:40

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


    1. DarkEld3r
      22.12.2019 23:15

      Дык, все живые языки развиваются. Даже в го, киллер фичей которого считаю простоту освоения, дженерики завезти хотят.


      И с другой стороны: столько нужных фич в расте ещё не сделаны! (:


      1. epishman
        23.12.2019 00:01

        Го еще жив? Вроде туда вот-вот исключения планировали завести, но я уже потерял интерес, как и к Dart. Похоже, акела промахнулся, хотя на Flutter еще надежда теплится.