LINUX.ORG.RU

Вышел Rust 1.8

 


3

7

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

Как обычно, вы можете установить Rust 1.8 с соответствующей страницы на нашем сайте и посмотреть подробные примечания к выпуску 1.8 на GitHub'е. В этом релизе было принято около 1400 патчей.

Что нового в стабильной версии 1.8

Этот выпуск содержит два нововведения, и приятный сюрприз для пользователей Windows! Помимо этого идёт работа по замене системы сборки Rust, основанной на make, на Cargo.

Первое нововведение – это возможность перегрузки составных операторов присваивания, таких как += и -=. Изменение было принято в RFC 953 и выглядит следующим образом:

use std::ops::AddAssign;

#[derive(Debug)]
struct Count { 
    value: i32,
}

impl AddAssign for Count {
    fn add_assign(&mut self, other: Count) {
        self.value += other.value;
    }
}   

fn main() {
    let mut c1 = Count { value: 1 };
    let c2 = Count { value: 5 };
    c1 += c2;
    println!("{:?}", c1);
}

Эта программа выведет Count { value: 6 }. Как и в других трейтах, перегружающих операторы, ассоциированный тип позволяет использовать разные типы в левой и правой части оператора (см. RFC 953).

Второе нововведение, взятое из RFC 218, не такое значительное. В предыдущих версиях Rust структура, не содержащая полей, должна была объявляться без фигурных скобок:

struct Foo; // works
struct Bar { } // error

Вторая форма объявления больше не является ошибочной. Изначально эта форма была запрещена из соображений согласованности с другими пустыми объявлениями, а также для предотвращения неоднозначности синтаксического разбора. Но эта неоднозначность была устранена, начиная с Rust 1.0. Кроме того, запрет этой формы создавал трудности при написании макросов, требуя специальной обработки. Наконец, пользователям, ведущим активную разработку, иногда требовалось менять пустую структуру на непустую и наоборот, что требовало лишней работы и приводило к некрасивым diff'ам.

Возвращаясь к Windows — теперь 32-х битные MSVC сборки поддерживают размотку стека, что переводит платформу i686-pc-windows-msvc в класс 1 (о классах поддержки платформ).

Мы с давних пор используем make для сборки Rust'а, но у нас уже есть своё замечательное средство сборки для программ на Rust: Cargo. В Rust 1.8 мы добавили предварительную поддержку новой системы сборки, написанной на Rust и основанной на Cargo. Мы ещё не используем её по умолчанию, и она требует значительной доработки, поэтому подробное её описание появится в примечаниях к выпуску после её завершения. Сейчас вы можете посмотреть подробности по ссылке на PR 31123.

Стабилизация библиотек

В Rust 1.8 около 20 функций и методов было переведено в категорию стабильных. Их можно разбить на три группы: работа со строками в кодировке UTF-16, различные API для работы со временем, и дополнительные трейты, необходимые для перегрузки операторов, упомянутые в секции об изменениях в языке.

Нововведения в Cargo

  • cargo init создаёт проект в текущем каталоге, не создавая новый, как делает cargo new
  • cargo metadata - дополнительная субкоманда для получения метаданных
  • .cargo/config теперь допускает ключи -v и --color
  • Улучшены возможности Cargo по поддержке платформоспецифичных зависимостей.

Подробное описание изменений.

>>> Вышел Rust 1.8

★★★

Проверено: maxcom ()
Последнее исправление: shahid (всего исправлений: 5)
Ответ на: комментарий от tailgunner

А попробуй посчитать.

Разве есть сомнения? В плюсах при вызове функции (которая принимает ссылку) амперсанд писать не надо. Да и в тех случаях (пусть и редких), когда надо явно указать дженерик параметры при вызове функции, приходится писать foo::<i32>(...), а в крестах :: не требуется в этом случае.

Другое дело, что первое, как по мне, даже удобно.

DarkEld3r ★★★★★
()

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

makoven ★★★★★
()
Ответ на: комментарий от tailgunner

цифры любопытны.

Посчитал. Для сравнения взял исходники rust 1.8.0 и clang trunk. Оба компиляторы, оба основаны на llvm так что сравнение должно быть честным. Для раста брал файлы *.rs (6737 шт.) для c++ брал файлы *.h (1407 шт.) и *.cpp (3896 шт.)

clang (1'303'325 lines) (47'657'970 chars)
:: per line 0.101192718624
:: per char 0.00276736503884
&  per line 0.0386680221741
&  per char 0.00105747265358

rustc (613'898 lines) (21'761'074 chars)
:: per line 0.149532984307    (1.47x)
:: per char 0.00421844987982  (1.52x)
&  per line 0.0914923977599   (2.36x)
&  per char 0.0025810766509   (2.44x)
pftBest ★★★★
()
Ответ на: комментарий от anonymous

Стабильная версия будет выходить раз в 6 недель.

anonymous
()
Ответ на: комментарий от DarkEld3r

не ну постепенное добавление полей в структуру - это ок, я понимаю. Я не понимаю именно чередование туда-сюда

arcanis ★★★★
()

И как всегда в тему набежали упоротые лисперы.
Граждане, идите дрочите на свои s-выражения в другом месте.

WatchCat ★★★★★
()

Вроде полгода назад 1.0 вышел. А уже 1.8.

utf8nowhere ★★★
()

И откуда столько скобкодрочеров развелось?

templarrr ★★★★★
()
Ответ на: комментарий от h4tr3d

:: и & в плюсах меньше?

Да, там вместо, например:

let r = Rect::new(Point2D::new(0i32, 0i32), Size2D::new(w, h));

Пишется:

Rect r({}, {w, h});

С move-семантикой, как минимум, & стало ещё больше :)

Отдельные методы с prvalue выписываются как оптимизация, и там && пишется только в типе параметра. А T::new(...) в Rust это суровая необходимость.

Аналогично можно взять &self, который заставляют писать руками и пр.

anonymous
()
Ответ на: комментарий от anonymous

let r = Rect::new(Point2D::new(0i32, 0i32), Size2D::new(w, h));
Rect r({}, {w, h});

Хотя нет, я ж забыл, в Rust нет перегрузки функций. Вот они и маются. В С++ будет:

Rect r( w, h );
anonymous
()
Ответ на: комментарий от anonymous

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

А в чём проблема? Гентушник, чтоле?

anonymous
()
Ответ на: комментарий от anonymous

Собственно всё это началось с того, что у кого-то иррациональная боязнь :: и &. Так что не слишком важно.

Отсутствие перегрузки пожалуй неприятно, но зато можно выкинуть килобайты правил overloading resolution. Да и написать однострочную fn xywh_to_rect(i32,i32,u32,u32) -> Rect, не так уж и сложно.

self, &self, &mut self нужны из-за разной семантики. Внутри метода можно было бы и выкинуть, но тут приоритет явного над неявным.

red75prim ★★★
() автор топика
Ответ на: комментарий от Xroft

Синтаксис у него просто вырвиглазный.

Дело привычки.

segfault ★★★★★
()

Падаригмы программирования.

Я думал Раст как замена опасной сишке. Ан нет, раст не замена сишке, раст сам по себе. Вот Википедии прочитал, оказывается раст поддерживает, структурное (как в си?), функциональщину (математики довольны), объесто-ориентированную падаригму.

Нет-нет, нет и нет! Вы уж какой-то один способ кодирования выберите.

anonymous
()
Ответ на: комментарий от red75prim

Отсутствие перегрузки пожалуй неприятно, но зато можно выкинуть килобайты правил overloading resolution.

Можно выкинуть много чего, что уж там. А так это шаг назад как для языка со статической типизацией. Данную фичу имеет как и относительно примитивная Java, так и новомодный Swift (привет, tailgunner).

Да и написать однострочную fn xywh_to_rect(i32,i32,u32,u32) -> Rect, не так уж и сложно.

Очевидный костыль. неочевидный в использовании.

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

А почему тогда return писать можно не всегда? Где тут приоритет? Да и зачем писать имя параметра, который нельзя переименовать? Зато, если в swift (привет, tailgunner) можно вызвать функцию с именованным аргументом «foo( n: 100 )», то в Rust нельзя. А ведь тут явное указание действительно имеет важное значение - так можно безопасно рефакторить код, и можно избежать случайных логических ошибок.

anonymous
()
Ответ на: комментарий от anonymous

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

Тут еще стоит добавить про то, что явное имя параметра почему не мешает упускать неявный тип параметра. Приоритеты явного надо неявным такие приоритетные.

anonymous
()
Ответ на: комментарий от anonymous

В моём небольшом (тысячи 4 SLOC + тысяч 8 автогенерированных SLOC) проекте отсутствие перегрузки пока не особо мешало.

Очевидный костыль. неочевидный в использовании.

Хм. Чего уж тут неочевидного? По названию/сигнатуре функции всё видно. А костылей везде хватает. Взять хотя бы плюсовый tie - костыль для отсутствующего pattern matching.

А почему тогда return писать можно не всегда?

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

Именованные параметры, вроде бы, собираются добавлять.

red75prim ★★★
() автор топика
Ответ на: комментарий от red75prim

Чего уж тут неочевидного?

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

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

А все методы обязаны иметь self. И даже исключений нет.

anonymous
()
Ответ на: комментарий от anonymous

А все методы обязаны иметь self. И даже исключений нет.

И это правильно. Вот как ты без него запишешь это?

fn foo() {}
fn foo(self) {}
fn foo(&self) {}
fn foo(&mut self) {}
anonymous
()
Ответ на: комментарий от anonymous

А тут же тебе приходится писать костыльную функцию, которая исполнять роль конструктора.

Если мне понадобится создавать тучу Rect'тов из x,y,w,h сделаю

trait MyKostyl { fn from_xywh(i32,i32,u32,u32)->Self }
impl MyKostyl for Rect { ... }
let r = Rect::from_xywh(0,0,100, 200); // автокомплит сработает

red75prim ★★★
() автор топика
Ответ на: комментарий от anonymous

Вот собственно и проблема. Смотришь ты в документацию, и ищешь где-то в конце эти модификаторы или его отсутствие. Не удобно.

fn foo(arg0: FooBarFooBar, arg1: Other, arg2: FooBar) mut -> FooBar {}

// сразу видно как используется объект
fn foo(&mut self, arg0: FooBarFooBar, arg1: Other, arg2: FooBar) -> FooBar {}
anonymous
()
Ответ на: комментарий от red75prim

Если мне понадобится создавать тучу Rect'тов из x,y,w,h сделаю

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

автокомплит сработает

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

anonymous
()
Ответ на: комментарий от anonymous

Вот собственно и проблема. Смотришь ты в документацию, и ищешь где-то в конце эти модификаторы или его отсутствие. Не удобно.

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

anonymous
()

Rust - это хорошо, но количество писанины превышает даже C++. Swift в этом плане выглядит более привлекательно.

PS: тред-детектор лисперов

RazrFalcon ★★★★★
()
Ответ на: комментарий от Oxdeadbeef

Синтаксис конечно.
Избранные теги: clos, common lisp, emacs, emacs lisp, erlang, lisp, lispworks, machine learning, ml, prolog, sbcl

Спасибо, повеселил.

anonymous
()

Мужики, а rust-book актуален еще? А то стал читать перед сном, когда дочитаю выйдет уже rust 2.0

dnb ★★★★
()
Ответ на: комментарий от red75prim

fn foo(mut self) {}` можно записать как fn foo(self) {let mut _self = self;}

Явное против неявного - что выберешь?

struct Foo {
    a: i32,
    b: u32,
}

fn bar(foo: &Foo) -> i32 {
    foo.a
}

fn baz(&Foo { a, .. }: &Foo) -> i32 {
    a
}

shaiZaigh
()
Ответ на: комментарий от anonymous

Rect r({}, {w, h});

Ну офигеть. Конкурс «угадай что эта хрень значит».

А в растовском варианте все очевидно.

anonymous
()
Ответ на: комментарий от anonymous

Ну офигеть. Конкурс «угадай что эта хрень значит».
А в растовском варианте все очевидно.

Ну пиши так:

Rect r(Point2D(), Size2D(w, h));

Всяко гораздо лучше бесполезных ::new.

anonymous
()
Ответ на: комментарий от red75prim
    match addr.to_socket_addrs() {
        Ok(r) => {
            for a in r {
                match a {
                    SocketAddr::V4(_) => {
                        if proto == InternetProtocol::Any || proto == InternetProtocol::IpV4 {
                            match TcpStream::connect(&a) {
                                Ok(s) => {
                                    return Ok(s);
                                }
                                Err(e) => {
                                    println!("some error: {}", e);
                                }
                            }
                        }
                    }
                    SocketAddr::V6(_) => {
                        if proto == InternetProtocol::Any || proto == InternetProtocol::IpV6 {
                            match TcpStream::connect(&a) {
                                Ok(s) => {
                                    return Ok(s);
                                }
                                Err(e) => {
                                    println!("some error: {}", e);
                                }
                            }
                        }
                    }
                }
            }
            Err("Could not connect")
        }
        Err(_) => Err("Could not resolve"),

вся суть руста

anonymous
()
Ответ на: комментарий от anonymous

Я не специалист по расту, но если хочется избавиться от дублирования кода, то можно условие if-а вытащить в переменную, а при её присваивании уже матчиться по типу a. А накопипастить с лёгкостью можно в любом языке программирования.

Softwayer ★★
()
Ответ на: комментарий от dnb

Мужики, а rust-book актуален еще? А то стал читать перед сном...

Ты в качестве снотворного читаешь штоле?? :))))

...когда дочитаю выйдет уже rust 2.0

Ну и хорошо! Вторая версия выйдет ещё более усыпляющей. :D

Мне кажется, Rust не взлетит. Поклонников наберёт (как Ди), но влезать на рынок, где всё поделено между Жабой, Сипипями и C# - нереально. Джабистам и шарпофилам такое УГ не нужно. А сипиписники не для того прошли тысячи граблей, чтобы вот так просто намотать на граблю поролон! Один синтаксис С++ въелся им в мозг так, что от других языков они будут плеваться. А ещё «чужие» либы, среды, методологии...

ИТ слишком долго стагнировала в посредственных (зато мэйнстримовых!) языках, чтобы какой-то выскочка мог изменить положение сил.

matumba ★★★★★
()
Ответ на: комментарий от matumba

А сипиписники не для того прошли тысячи граблей, чтобы вот так просто намотать на граблю поролон!

ну я сипиписник. уже год наматываю раст. В плане синтаксиса та еще наркомания, особенно лайфтаймы. Зато можно писать write-only код, который потом сам через месяц уже хер прочитаешь :)

А вообще преимуществ каких-то особых не нашел. переписал либу для ASN1 и для внутреннего RPC.

anonymous
()
Ответ на: комментарий от anonymous
    match addr.to_socket_addrs() {
        Ok(r) => {
            for a in r {
                match (a, proto) {
                    (_, InternetProtocol::Any)
                    | (SocketAddr::V4(_), InternetProtocol::IpV4)
                    | (SocketAddr::V6(_), InternetProtocol::IpV6) =>
                        match TcpStream::connect(&a) {
                            Ok(s) => {
                                return Ok(s);
                            }
                            Err(e) => {
                                println!("some error: {}", e);
                            }
                        },
                    _ => (),
                }
            }
            Err("Could not connect")
        },
        Err(_) => Err("Could not resolve"),

quantum-troll ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.