По-моему, это самый полезный выпуск Раста за долгое время. Одни трейты в параметрах и результате чего стоят!

Impl trait крутая штука, но стоит заранее ознакомиться с нюансами их употребления, что бы потом не напороться неожиданно на сюрприз: https://www.reddit.com/r/rust/comments/8ik620/notes_on_impl_trait/


допустим, турборыба (func::<MyType>) для них вообще не работает

Это происходит потому, что impl Trait определяет анонимизированный тип. То есть он скрывает имя реально используемого типа, а не позволяет использовать множество разных типов в этом месте, как делают переменные типа <T: Trait> статически или Box<Trait> динамически. Вот пример:


fn foo<T: Clone>(a: &T) -> T {
    a.clone()
}

fn bar(a: &impl Clone) -> impl Clone {
    a.clone()
}

fn main() {
    let a: f32 = foo(&2.5); // Ok
    let b: i32 = foo(&5); // Ok
    let c: i32 = bar(&5); // Error: expected i32, found anonymized type
}

https://play.rust-lang.org/?gist=c0adf6c27c0554d11e3f172cdce32bc7&version=stable&mode=debug


В случае с функцией bar мы лишили результирующий тип имени и как бы урезали его до возможностей типажа Clone. Но не более: никакой возможности использовать разные типы в этом месте, как у foo, мы не получили.

Однако в позиции аргумента impl Trait ведет себя по-другому, а именно — как универсальный тип. Поэтому такой код корректен:


let d = bar(&5_f32);
let e = bar(&5_i32);

Хотя результирующие типы для d и e мы указать не можем.

на этот год запланирован мажорный релиз, самый крупный со времен 1.0. impl Trait как раз входит в его роадмап

Посоветуйте, пожалуйста, тем, кто хочет познакомиться и начать применять раст: на что методически и идеологически похож раст? Мне он напоминает нелюбимого сына С++ и Хаскеля, но я скорее всего ошибаюсь, почти ничего на нём не написал.
нелюбимого сына С++ и Хаскеля
Внебрачный ребенок C и OCaml-а.
Несмотря на все различия этих технологий, общее впечатление от разработки на Rust скорее близко к впечатлению от разработки на Java, чем на C.
Методически он похож на оба упомянутых вами языка. Выглядит это так, что программа пишется в традиционном императивном стиле, приправленном, однако, идиомами из мира ФП. Очень много внимания уделяется комбинаторам и правильной работе с итераторами. В итоге получается удобнейший сплав императивщины и ФП, который позволяет очень комфортно и безопасно обрабатывать потоки данных. Обработка ошибок тоже очень своеобразная, что, впрочем, не делает ее сложной, скорее наоборот.

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

Разве не какой-нибудь Clean запионерил линейные типы?
Я говорю про распространенные языки на которых можно писать в продакшне хоть сейчас. Если попытаться собрать в одном языке все эти качества:

  • Императивная основа (не ФП)
  • Целостная и непротиворечивая система типов
  • ФП идиомы, но с возможностью «срезать углы»
  • Близость к железу (можно программировать микроконтроллеры)
  • Отсутствие рантайма и минимальный footprint
  • Поддержка множества платформ (не только x86)
  • Статически безопасная работа с памятью без GC
  • Статически безопасная работа с многопоточностью
  • Хорошая документация
  • Четкий и внятный roadmap
  • Активное и дружелюбное сообщество


…то кроме Rust назвать будет пожалуй что и нечего.

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

Я совсем не растоман, но читал год-два назад пару RFC и обсуждений на тему проблем с borrow checker'ом, и у меня сложилось впечатление, что Rust скорее взял именно что идею, но без сурового математического формализма, лежащего в его основе.
Ну, изначально вы говорили лишь о языках общего назначения :)
Буду признателен, если вы назовете мне еще один ЯП, который позволяет статически на этапе компиляции доказать отсутствие гонок в коде. Насколько я знаю, это новшество появилось именно в Rust и является прямым следствием его системы типов.

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

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

Да, корректность многих частей не была до поры формально доказана, но это было исправлено, когда Ralf Jung с коллегами в рамках проекта Rust Belt проверил и формально доказал корректность инвариантов языка, а также основных компонентов его стандартной библиотеки.

Языку в некотором смысле повезло, поскольку в ядре команды оказалось сразу несколько толковых специалистов по компиляторам и теориям типов, что в конечном итоге определило его успех.
Rust похож на C++ без классов (Go-like интерфейсы) и постоянно включенным очень злым статическим анализатором. И нормальным пакетным менеджером :)

Также, Rust похож на Go с дженериками и постоянно включенным очень злым статическим анализатором. И нормальным пакетным менеджером :)
Начни! И сразу все поймешь! Не надо тут гадать.
Эх, что за любовь выбирать символы позаковыристее. Наверняка возможно составить грамматику с указанием вхождения границ почеловечнее:
for i in [0..256) { ... }

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

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

Или если уж очень хочется переложить на людей, то можно же было реиспользовать троеточие, было бы хотя бы консистентно:
for i in 0...255 { ... }

А не две разные нотации диапазона, включающего верхнюю границу =(.

В будущем ... в паттернах также заменят на ..=. Сейчас уже работает эта конструкция как псевдоним: https://github.com/rust-lang/rust/issues/28237


А насчет [0..256), то это выглядит хорошо только для простейшего случая с константами. А если границы будут определяться сложнее? Разные виды скобок будут плохо восприниматься не только парсером, но и человеком. Более того, придется все время искать правую границу выражения, чтобы по скобке определить тип диапазона. Тогда как с синтаксисом ..= тип диапазона виден сразу.


Но соглашусь, что ..= тоже не идеален, особенно в паттернах if let:


if let 1..=5 = a {
    // тело
}

Но пока это лучшее, до чего договорилось сообщество. Если у вас есть альтернативные идеи — то добро пожаловать на GitHub, вы всегда можете высказать свое предложение в соответствующем issue :)

[0..256)

Несбалансированные скобки это убивство как минимум для системы макросов Rust.
Макросы могут принимать на вход любую последовательность токенов (m!( a ; d89 d ** 38 +() {} 'd )) с единственным ограничением — ()[]{} скобки должны быть сбалансированы, т.к. сбалансированная закрывающая скобка это единственный способ определить где вызов макроса заканчивается.


можно же было реиспользовать троеточие

Оно и было ... сначала, но люди очень громко жаловались что слишком похоже на .., без очков разницы не видно. Люди с decision power на жалобы поддались и выбрали вместо него этот страшный ..=, типа стерпится-слюбится, зато разницу сразу видно.

На мой вгляд было бы уместно использовать ..< и ..=
Math
exclusive: [a..b), inclusive: [a..b]
Haskell
exclusive: <none>, inclusive: a..b
Elixir
exclusive: <none>, inclusive: a..b
Ruby
exclusive: a...b, inclusive: a..b
Swift
exclusive: a..<b, inclusive: a...b
Rust
exclusive: a..b, inclusive: a...b

Language designers be trolling. ¯_(ツ)_/¯

vs ..= for inclusive ranges

Да там на протяжении трех лет и целой пачки РФЦ тысячи комментариев были написаны вообще со всеми возможными вариантами и супер-подробным разбором их достоинств и недостатков — достаточно загуглить "rust rfc range syntax" или что-то подобное. Очень субъективная тема, у всех свои предпочтения, у всех вариантов есть недостатки. И еще вопрос крайне простой, у каждого есть веское мнение — это тебе не тонкости реализации HKT обсуждать.


Сейчас-то какой уже смысл обсуждать? Если так интересно будущее языка, имеет смысл посмотреть какие RFC сейчас находятся в стадии обсуждения и там участвовать.

Если знаний в разработке языков особо нет, а делиться мнением очень хочется, то вот текущее RFC по стилю отлично подходит, например — https://github.com/rust-lang/rfcs/pull/2436 — гигантский простор для споров о субьективной ерунде.

Язык должен жить и развиваться :) Если в сотый раз новые люди наталкиваются на одни и те же проблемы с синтаксисом, и в сотый раз нужно одно и то же рассказывать им о нем — то вообще, это может свидетельствовать о недостаточной организованности и канализированности данной темы. А если она уже канализирована — то пусть в своем канале она и обсуждается, глядишь, со временем может что еще новенькое родится там. Это — нормально.
Что-то все кабанеет Раст и кабанеет.
Только полноправные пользователи могут оставлять комментарии.
Войдите, пожалуйста.