Комментарии 24
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
мы указать не можем.
нелюбимого сына С++ и ХаскеляВнебрачный ребенок C и OCaml-а.
А вот идеологически Rust пока единственный в своем роде, ибо подобного уровня контроля в языках общего назначения еще не было. Не говоря уже о фундаментальном отсутствии ошибок работы с памятью и состояний гонок, без обычно связанных с этим накладных расходов вроде сборщика мусора.
- Императивная основа (не ФП)
- Целостная и непротиворечивая система типов
- ФП идиомы, но с возможностью «срезать углы»
- Близость к железу (можно программировать микроконтроллеры)
- Отсутствие рантайма и минимальный footprint
- Поддержка множества платформ (не только x86)
- Статически безопасная работа с памятью без GC
- Статически безопасная работа с многопоточностью
- Хорошая документация
- Четкий и внятный roadmap
- Активное и дружелюбное сообщество
…то кроме Rust назвать будет пожалуй что и нечего.
Ну и если придираться, то в Rust используются аффинные типы, а не линейные. Потом, как мне кажется, важен не тот язык, где запионерили ту или иную идею, а тот, где ее довели до ума и которой действительно можно комфортно пользоваться изо дня в день.
Ну, изначально вы говорили лишь о языках общего назначения :)Буду признателен, если вы назовете мне еще один ЯП, который позволяет статически на этапе компиляции доказать отсутствие гонок в коде. Насколько я знаю, это новшество появилось именно в Rust и является прямым следствием его системы типов.
Rust скорее взял именно что идею, но без сурового математического формализма, лежащего в его основе.Rust — это практичный, а не академический язык и эволюционировал он с прицелом на удобство использования, а не академическую чистоту/новизну. Однако это не означает, что в его основе нет строгости.
Иначе бы грош цена была всему анализу и нельзя было бы утверждать, что программа, написанная на безопасном подмножестве Rust действительно корректна.
Да, корректность многих частей не была до поры формально доказана, но это было исправлено, когда Ralf Jung с коллегами в рамках проекта Rust Belt проверил и формально доказал корректность инвариантов языка, а также основных компонентов его стандартной библиотеки.
Языку в некотором смысле повезло, поскольку в ядре команды оказалось сразу несколько толковых специалистов по компиляторам и теориям типов, что в конечном итоге определило его успех.
Также, 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 на жалобы поддались и выбрали вместо него этот страшный ..=
, типа стерпится-слюбится, зато разницу сразу видно.
Да там на протяжении трех лет и целой пачки РФЦ тысячи комментариев были написаны вообще со всеми возможными вариантами и супер-подробным разбором их достоинств и недостатков — достаточно загуглить "rust rfc range syntax" или что-то подобное. Очень субъективная тема, у всех свои предпочтения, у всех вариантов есть недостатки. И еще вопрос крайне простой, у каждого есть веское мнение — это тебе не тонкости реализации HKT обсуждать.
Сейчас-то какой уже смысл обсуждать? Если так интересно будущее языка, имеет смысл посмотреть какие RFC сейчас находятся в стадии обсуждения и там участвовать.
Если знаний в разработке языков особо нет, а делиться мнением очень хочется, то вот текущее RFC по стилю отлично подходит, например — https://github.com/rust-lang/rfcs/pull/2436 — гигантский простор для споров о субьективной ерунде.
Выпуск Rust 1.26