LINUX.ORG.RU

Rust 1.26

 


5

11

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

Обновить Rust можно с помощью команды:

curl https://sh.rustup.rs -sSf | sh # если у вас еще не установлен rustup
rustup update stable

Основные изменения:

  • Вторая редакция книги «The Rust Programming Language» (почти) готова, и теперь рекомендована по умолчанию для ознакомления вместо первой версии. Также готовится к выходу бумажное издание книги.
  • impl Trait в заголовках функций

    Стало возможно указывать Trait в заголовке функции в качестве типа возвращаемого значения:

    fn foo() -> impl Iterator<Item = i32> {
        // ...
    }
    
    Это позволяет не указывать полный тип в заголовке функции, если с точки зрения API конкретный тип не имеет значения. Такой синтаксис подразумевает статическую диспетчеризацию, в отличие от Box<Trait>.

    Также эта возможность удобна для использования с замыканиями (closures):

    fn foo() -> impl Fn(i32) -> i32 {
        |x| x + 1
    }
    

    Новый синтаксис теперь можно использовать и для типов аргументов фунции:

    // раньше нужно было писать так:
    fn foo<T: Trait>(x: T) {
    
    // сейчас можно так:
    fn foo(x: impl Trait) {
    

  • Неявное разыменование ссылок в сопоставлении с образцом (match, if let, ...)

    Теперь следующий код больше не вызывает ошибку компиляции:

    fn hello(arg: &Option<String>) {
        match arg {
            Some(name) => println!("Hello {}!", name),
            None => println!("I don't know who you are."),
        }
    }
    
    и эквивалентен такому:
    fn hello(arg: &Option<String>) {
        match arg {
            &Some(ref name) => println!("Hello {}!", name),
            &None => println!("I don't know who you are."),
        }
    }
    
    То же работает и для &mut + ref mut.

  • Раскрытие срезов (slice) в сопоставлении с образцом
    fn foo(s: &[u8]) {
        match s {
            [a, b] => (),
            [1, _, _] => (),
            _ => (),
        }
    }
    
  • Закрытые интервалы вида 0..=4, включающие обе границы в диапазон перечисления
        for i in 0..=4 {
            println!("i: {}", i); // выведет 0, 1, 2, 3 и 4
        }
    
  • Новые целочисленные типы i128 и u128
  • Функция main() теперь может возвращать тип Result
    use std::fs::File;
    
    fn main() -> Result<(), std::io::Error> {
        let f = File::open("bar.txt")?;
    
        Ok(())
    }
    
  • Ускорения в работе компилятора
  • Стабилизирована функция std::fs::read_to_string
  • При форматировании через trait Debug теперь можно выводить целочисленные значения в шестнадцатеричном виде:
    assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]")
    
  • Номер версии Cargo, начиная с этого релиза, изменяется синхронно с номером версии Rust

>>> Подробности

★★★★★

Проверено: Shaman007 ()
Последнее исправление: tailgunner (всего исправлений: 22)
Ответ на: комментарий от RazrFalcon

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

Вот это правильно.

На 146% надеюсь?

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

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

Я не фанбой, просто так выражаюсь. (с)

Подколол, да)) Но я и про Раст также скажу - у него тоже выдающиеся возможности. Они просто другие чем у Го или Ди.

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

Объекты уходят во владение функциям продолжения flat_map/and_then, функции map и тому подобного. Далее объекты более нельзя использовать из контекста вызова. Исключительно технический момент, но который имеет решающее значение для языка без сборки мусора.

Но я и так слишком много сказал ;)

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

С чего бы? Если решение «поставленной задачи» можно написать на Rust или, прости ТНБ, на Go - с чего бы платить Си-программисту больше?

Мысль моя в том, что Го или Раст за счет своей продуманности не дадут написать быдлокод там где его можно написать на Си. Т.е. свобода, которую дает Си, требует высокой квалификации от кодера. А за это нужно платить.

А у D много мелких коммерческих пользователей? Откуда данные?

По данным ИМХО)) Ну как бы цифры то откуда я возьму? На форумах люди задают вопросы, причем не такие как здесь, а грамотные по поводу подводных камней при переходе на Ди. Им также грамотно отвечают, кто-то в итоге переходит, кто-то нет. Люди конкретно описывают свой кейс, например, эмбедщина, вот хотят то-то и то-то. Т.е. это не треп как здесь, а именно по существу обсуждения. Александреску когда ездил в Израиль писал в блоге или где-там что был удивлен количеством стартапов в Израиле где использовался Ди и что уровень разработки был высок, при этом этих людей он встречал впервые. И это не только Weka. Регулярно всплывает информация то там, то там. Ди явно растет и развивается, как и его инфраструктура. Но если вам не нравится Ди, вы конечно не обязаны его использовать)) По хайпу Ди очень уступает Расту, вне всяких сомнений.

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

То, что для задачи «сервить хелловорлд» нужно выбирать Go

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

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

свобода, которую дает Си, требует высокой квалификации от кодера. А за это нужно платить.

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

А у D много мелких коммерческих пользователей? Откуда данные?

По данным ИМХО))

Ясно.

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

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

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

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

че-то я совершенно не разделяю и твоих восторгов, и твоих претензий

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

и насчет претензий — в математике функция никогда не потребляет (consume) свои аргументы, так что говорить «не совсем монада» именно по этой причине в принципе можно, но как-то уж очень мелко — я-то думал, что там будет что-то похожее на монаду, но не монада, и заинтересовался этим

www_linux_org_ru ★★★★★
()
Последнее исправление: www_linux_org_ru (всего исправлений: 3)
Ответ на: комментарий от tailgunner

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

Либо я не ясно выразился либо ты не понял.

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

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

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

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

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

Пока пойдем за Си++ (из которого, в общем-то, можно сделать эрзац-Rust),

Очень уж эрзац получится. По принципу мыши кололись, плакали, но продолжали есть кактус.

А если честно из плюсов сделать что-то подобное Расту можно только написав новый язык. Т.е. нельзя, не нужно себя тешить.

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

Еще раз объясню свою мысль - нет смысла нанимать сишного высококвалифицированного кодера, если это можно написать проще и дешевле на Го или Расте.

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

А если честно из плюсов сделать что-то подобное Расту можно только написав новый язык.

Да? Ну окей, не стану спорить. Вполне возможно, что ты знаешь и Rust, и Си++ лучше, чем я.

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

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

Вот именно поэтому, работа Си-кодеров не

будет ограничена легаси-кодом на Си.

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

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

Пля, ну ты же про тоже самое говоришь что и я, но почему-то формулируешь это в виде отрицания моих слов. Зачем?))

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

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

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

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

Так как в определенных задачах нужна свобода, которую дет Си

Си не дает никакой особой свободы по сравнению с Rust или Си++

Хотя я бы заменил Си на что-то более выразительное, но, к сожалению, Nim, видимо, не взлетит...

Бгг. Там, где Си можно заменить на покойный Nim, его можно заменить чем угодно. Хоть JavaScript.

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

Давай, умник, напиши ка нам систему жесткого реального времени на JS!

После того, умник, как ты напишешь мне такую систему на Nim!

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: impl Trait для параметров функций? от anonymous

На самом деле всё просто. Дженерики - это... дженерики, шаблоны, если по-сипыпышному, описание как создавать подобные структуры или функции для разных типов. Impl Trait - это не другой способ описать дженерик, это более высокоуровневая фича, которая в одном случае реализуется через дженерик, а в другом иначе. Возмущаться такой непоследовательностью - это всё равно что возмущаться тем, что какой-нибудь компилятор умножение на степень двойки реализует через сдвиг влево, а другие умножения через специальную команду. С impl Trait всё понятно, «значение типа, реализующего Trait». Когда такое на входе, функция становится дженериком. Когда на выходе - «дженериком» становится вызывающий функцию код.

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

Когда на выходе - «дженериком» становится вызывающий функцию код.

Когда impl Trait на выходе, то ничего дженериком не становится, даже в кавычках. В месте вызова функция возвращает конкретный тип, но этот тип - анонимен.

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

Зачем мне насиловать труп?

А я даже живых насиловать не стану. Особенно ради чужого удовольствия.

Но это не значит, что люди не пытались

Проекты ОС на JS ты можешь найти сам.

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

регулярки на пёрдле

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

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

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

~ siege -c8 -b -t3S  http://127.0.0.1:3000/
** SIEGE 4.0.4
** Preparing 8 concurrent users for battle.
The server is now under siege...
Lifting the server siege...
Transactions:		       72139 hits
Availability:		      100.00 %
Elapsed time:		        2.63 secs
Data transferred:	        0.89 MB
Response time:		        0.00 secs
Transaction rate:	    27429.28 trans/sec
Throughput:		        0.34 MB/sec
Concurrency:		        6.78
Successful transactions:       72139
Failed transactions:	           0
Longest transaction:	        0.01
Shortest transaction:	        0.00

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

[package]
name = "test"
version = "0.0.1"
include = [
  "Cargo.toml",
]

[dependencies]
hyper = "0.11.26"
num_cpus = "1.8.0"
extern crate hyper;
extern crate num_cpus;

use hyper::server::{const_service, service_fn, Http, Response};

const TEXT: &str = "Hello, World!";

fn main() -> Result<(), hyper::Error> {
    let addr = ([127, 0, 0, 1], 3000).into();

    let hello = const_service(service_fn(
        |_req| Ok(Response::<hyper::Body>::new().with_body(TEXT)),
    ));

    /*
    let server = Http::new().bind(&addr, hello)?;
    server.run_threads(num_cpus::get());
    Ok(())
    */

    let server = Http::new().bind(&addr, hello)?;
    server.run()
}
** SIEGE 4.0.4
** Preparing 8 concurrent users for battle.
The server is now under siege...
Lifting the server siege...
Transactions:		       44920 hits
Availability:		      100.00 %
Elapsed time:		        2.49 secs
Data transferred:	        0.56 MB
Response time:		        0.00 secs
Transaction rate:	    18040.16 trans/sec
Throughput:		        0.22 MB/sec
Concurrency:		        7.21
Successful transactions:       44920
Failed transactions:	           0
Longest transaction:	        0.01
Shortest transaction:	        0.00
theromis
()
Ответ на: комментарий от anonymous

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

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

Оно может генерировать код на Си без внешних зависимостей, и при этом оно выразительно, как питон...

Хотя авторы не могут остановиться...

Вот если бы они стабилизировали ядро языка, я бы заюзал его в продакшоне.

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

Когда impl Trait на выходе, то ничего дженериком не становится, даже в кавычках. В месте вызова функция возвращает конкретный тип, но этот тип - анонимен.

В каком смысле анонимен? Компилятор не знает размер значения типа? Нет. Компилятор не знает, реализован ли для типа Drop? Опять нет, уничтожается всё как надо. Компилятор не знает конкретных функций и использует vtable? И тут нет, всё вызывается статически или даже инлайнится. Может анонимен как объект, созданный замыканием? И тут не так, если у возвращённого типа есть имя, оно известно компилятору. В общем ничего анонимного там в помине нет.

А что есть? А есть некий код, в котором тип переменной явно не специфициован и не может быть выведен (в расте вывод типа работает только внутри функции), указан только трейт и правильность кода проверяется на соответствие трейту. Позже, на этапе связывания функций будет выяснен настоящий тип переменной и сгенерирован код для конкретного этого типа. Ничего не напоминает? Дженерики. Так что я прав, а ты чушь сморозил.

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

А есть некий код, в котором тип переменной явно не специфициован и не может быть выведен (в расте вывод типа работает только внутри функции)

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

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от khrundel

И тут не так, если у возвращённого типа есть имя, оно известно компилятору.

До этого места всё почти правильно.

В общем ничего анонимного там в помине нет.

Тип анонимный, потому что он он существует, строго определён и известен компилятору, но не описан явным образом в коде (=у него нет имени).

А что есть? А есть некий код, в котором тип переменной явно не

специфициован и не может быть выведен

С этого места ты херню порешь.

в расте вывод типа работает только внутри функции

Ты херню порешь.

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

Ты херню порешь.

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

У авторов Nim полность отсутствую зайчатки вкуса и необходимый культурный багаж для создания красивого языка. Хуже Nim из современных недоязычков только Julia.

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

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

Да ты что!!! А я разве не это написал?

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

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

Да ты что!!!

Правда-правда.

А я разве не это написал?

Ты еще писал что-то про то, что тип нельзя вывести, про дженерики, про этап связывания. Это всё противоречит тому, что компилятор точно знает тип возврата.

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

Тип анонимный, потому что он он существует, строго определён и известен компилятору, но не описан явным образом в коде (=у него нет имени).

Предположим, этот тип i32. Есть у него имя? Есть. «i32». Анонимный тип это у замыкания например. Захваченные значения надо куда-то положить, компилятор создаёт тип для хранения, у него нет имени, он анонимен. Во всяких сишарпах можно анонимные типы прямо в коде создавать var a = new {i = 1, b = "aaaa" };. Вот это и есть анонимные типы. А если тип переменной просто коде не указан, он не становится анонимным.

Ты херню порешь.

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

Даже с появлением impl trait это не изменилось

trait MyTrait {}

impl MyTrait for i32 {}

fn get_my_trait () -> impl MyTrait { 1 }

fn main() {
    let a = 1;
    println!("a + 1 == {}", a + 1); // всё норм, тип a - i32, для него определена операция сложения.
    let b = get_my_trait();
    println!("b + 1 == {}", b + 1); // компилятор статически знает, что тип b - i32, но всё равно ошибка компиляции, тип b, с точки зрения семантического анализа, неизвестен, известно только что он MyTrait.
}
Т.е. вся работа с b ведётся так, как будто main - дженерик и переменная тип переменной b - параметр дженерика.

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

Ты еще писал что-то про то, что тип нельзя вывести, про дженерики, про этап связывания. Это всё противоречит тому, что компилятор точно знает тип возврата.

И это всё правда. Смотри на сообщение сразу под твоим.

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

. Смотри на сообщение сразу под твоим.

Я посмотрел. Если ты из _этого_ сделал вывод, что «вызывающий код становится дженериком» - думаю, ты в состоянии измененного сознания.

tailgunner ★★★★★
()

Параллельное вычисление на RUST

Тогда позвольте еще один вопрос по RUST. Вот допустим есть достаточно интенсивный поток запросов генерирующий картинку другого размера, относительно тяжелая логика, на go оно отлично отправляется в этот go lightthread, на RUST получается или использовать threadpool который может быстро кончиться при пиковой нагрузке, либо разбивать алгоритм на куски которые выполнять в асинхронном режиме, звучит как то через чур.

Есть еще какие то варианты выполнения этого?

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

Я посмотрел. Если ты из _этого_ сделал вывод, что «вызывающий код становится дженериком» - думаю, ты в состоянии измененного сознания.

Позорно сливаешься. Ну так что, реальный тип переменной b можно вывести? Вывести в том же смысле, как выведен тип переменной a? Заметь, речь даже не идёт про разные модули/крейты, вот тут, в рамках одного файла исходников. Ответ: нет. Полный аналог дженериков.

Ну и осознав что ты не прав, ты решил прикинуться дурачком и докопаться до термина, типа «не дженерик и всё тут». Но, во-первых, я слово «дженерик», в отношении вызывающего кода брал в кавычки, так что даже с буквоедской точки зрения ты не прав, а во-вторых, я выше объяснил, что общего у получающего impl trait из функции кода с кодом внутри дженерика. Есть что возразить - пожалуйста, а нет - сунь язык в жопу и свали посрамлённым.

khrundel ★★★★
()
Ответ на: Параллельное вычисление на RUST от theromis

на RUST получается или использовать threadpool который может быстро кончиться при пиковой нагрузке

Лол, а go при пиковой нагрузке разблокирует дополнительные ядра в процессоре?

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