LINUX.ORG.RU

Rust 1.7

 


1

6

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

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

В версии 1.7 были стабилизированы около 40 библиотечных функций и методов. Одним из стабилизированных API является поддержка задаваемых пользователем алгоритмов хеширования в типе HashMap<K, V> стандартной библиотеки. Теперь можно достигнуть значительного быстродействия за счёт возможности смены и использования более быстрого алгоритма хеширования.

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

  • <[T]>::clone_from_slice(), эффективный путь копирования данных из одного среза в другой срез.
  • Методы для удобства работы с Ipv4Addr и Ipv6Addr, такие как is_loopback(), который возвращает true или false, в зависимости от того, является ли адрес петлевым адресом, согласно RFC 6890.
  • Улучшения в CString, используемом в FFI.

Детальный RELEASE NOTES: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-170-2016-03...

>>> Анонс в блоге Rust

★★★★★

Проверено: tailgunner ()
Последнее исправление: cetjs2 (всего исправлений: 3)

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

лоровские анонимусы ещё руст в продакшыне не видели

/fixed

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

На http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna

Спасибо, отличный пример, кстати. У вебмакакофобов есть о чем подумать, а может они даже и попробуют (безуспешно ес-но) исправить свое унизительное положение.

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

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

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

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

Вэбом я не занимаюсь, а системное программирование, да и программирование вообще, у меня началось не с Rust, и даже не С,

а с ассемблеров.

Вангану: началось лабой в институте, и ей же закончилось.

Потому мне и смешно видеть «гуру», которым кровь из носу надо всегда гарантированно выделять память на стеке.

Ну давай помыделяй мне память в куче в прошивке для атмеги. Хотя ок, раст восьмибитные AVR'ы не поддерживает, так что можешь взять Cortex.

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

Мою точную цитату, или балаболка.

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

Спасибо, отличный пример

То-то оно использует preg_ из http://php.net/manual/en/book.pcre.php, а сам пых-пых pcre в зависимостях тянет.
А сразу сишную прогу запускать из пыха не пробовали?

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

На http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna

Просто устранили главного претендента. xD

Rust #2 Make Error
MAKE:
/usr/local/src/rust-1.7.0/bin/rustc -C opt-level=3 -C target-cpu=core2 -L /usr/local/src/rust_lib regexdna.rs -o regexdna.rust-2.rust_run
regexdna.rs:8:1: 8:20 error: can't find crate for `regex` [E0463]
regexdna.rs:8 extern crate regex;
              ^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
/home/dunham/benchmarksgame/nanobench/makefiles/u64q.programs.Makefile:627: recipe for target 'regexdna.rust-2.rust_run' failed
make: [regexdna.rust-2.rust_run] Error 101 (ignored)
0.10s to complete and log all make actions
anonymous
()

Программисты С++, которые в своё время убежали на Жабу. Переходите на новый мейнстримовый язык — Rust.

Прогаммисты «чистого Си», оставайтесь на местах, если конечно вы ещё живы. Ибо дзен «низкий уровень» имеет особую притягательную силу.

Мозилла гарантирует!

anonymous
()

Кстати, объясните мне одну штуку. В новости про 1.7 написано следующее:

Note that most of the time you don’t even need to specify the hasher as type inference will take care of it, so HashMap::default() should be all you need to get up to 2x faster hashes.

Как это работает? В смысле, что просто от импорта fnv::FnvHasher он подхватывается для хеш-мап?

DarkEld3r ★★★★★
()

Знатоки раста, откройте мне глаза. На данный момент есть 2 способа обработать события:

  1. Скармливаем все возможные коллбеки, либо даже используем замыкания
    Builder::new()
        .on_set(|x, y| println!("set {}:{}", x, y))
        .on_get(|x| println!("get {}", x))
        .build();
    В итоге мы как бы можем захватывать в замыкание прочие переменные, возможно придется обмазываться всякими мьютексами. Далее запускаем какой-нибудь event loop и наблюдаем за выводом на экране.
  2. Во втором варианте мы используем тип-сумму для получения событий, основная фича - т.к. в match срабатывает гарантированно одна из веток, то без проблем захватываются (даже мутабельные) переменные вне цикла, мьютексы и прочая синхронизирующая муть не нужна.
    enum Event {
        Set(i32, i32),
        Get(i32)
    }
    fn main() {
        /* ..... */
        for e in Builder() {
            match e {
                Event::Set(x, y) => println!("set {}:{}", x, y),
                Event::Get(x) => println!("get {}", x)
            }
        }
    }

Из-за безкостыльной работы с переменными вне цикла мне больше нравится второй способ, но насколько он эффективен? Прошу ответа на следующие два вопроса:

  1. enum Event явно имеет размер, равный сумме двух интов плюс какой-нибудь дискриминт и смещение, допустим 10 байтов. Но если в событии приходит Event::Set(x) - в памяти происходит копирование всех 10-ти байт или около 6-ти байт?
  2. В первом способе билдер сам подставляет переменные x и y в нужный коллбек, тогда получается их явно нужно где-то хранить. Значит ли это, что по потреблению памяти эти два способа практически идентичны?
anonymous
()
Ответ на: комментарий от anonymous

Но если в событии приходит Event::Set(x)

заменить на

Но если в событии приходит Event::Get(x)

Смысл в том, что Get(x) явно меньше занимает памяти, чем Set(x, y), но при этом они относятся к одному enum Event....

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

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

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

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

Из-за безкостыльной работы с переменными вне цикла мне больше нравится второй способ

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

в памяти происходит копирование всех 10-ти байт или около 6-ти байт

Не совсем понял, о чём ты. Тип Event явно должен иметь фиксированный размер вне зависимости от того, какое конкретно событие. А вот когда его копируют из одного места в другое, тут, думаю, зависит от компилятора. Если он решит, что быстрей делать memmove всей его памяти, то так и сделает, если решит, что быстрей проверить, какое событие и скопировать нужное число байт, то сделает так.

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

Rust поначалу еще больше колбасило.

Да, но это сознательно делалось до 1.0.

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

Кстати, кто знает, в расте можно циклические ссылки только через unsafe?

std::rc::Weak и никакого unsafe.

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

Дык в это-то и прикол, что если пришлось рефакторить, то в коде с вероятностью 95% есть:

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

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

А в Rust, повторюсь, нет классов, потому и разговор ни о чем.

Просто из любопытства: что тебе в растовых структурах не хватает? Ну кроме наследования данных.

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

И что тебе в трейтах не хватает по сравнению с «человеческими интерфейсами»?

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

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

И, все что есть в Rust, так же прекрасно размещается на стеке.

Ну размести мне трейты на стеке.

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

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

let vec: Vec<Box<T>> = vec![Box::new(A), Box::new(B), Box::new(C)];

В чём проблема?

А работа с трейтами как полями структур вообще огонь.

О чём речь?

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

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

Тебе не нравится, что нужно явно приводить к трейту? Ну так то строгая типизация виновата, трейты ни при чём.

А работа с трейтами как полями структур вообще огонь.

Ну ты скажи, что конкретно не так.

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

В чём проблема?

Ты это серьезно?

impl T for A {
    fn foo(&self) {
        println!("A");
    }
}

impl T for B {
    fn foo(&self) {
        println!("B");
    }
}

impl T for C {
    fn foo(&self) {
        println!("C");
    }
}

А если типов штук 100? на каждый придется импиметацию писать?

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

А если типов штук 100? на каждый придется импиметацию писать?

А как тебе «человеческие интерфейсы» помогут? Из атстрала будут читать, что ты вывести хочешь?

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

А если типов штук 100? на каждый придется импиметацию писать?

Аргумент - огонь. Типа: а если классов штук 100, это что каждому виртуальные функции оверрайдить придётся?

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

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

При желании можно mpsc использовать, но если таки всё в одном потоке должно быть? Тогда придется значения оборачивать в какой-нибудь контейнер, тот же Rc вроде блокирует асинхронность.

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

Ну давай помыделяй мне память в куче в прошивке для атмеги. Хотя ок, раст восьмибитные AVR'ы не поддерживает, так что можешь взять Cortex.

Замечательно, тогда я беру сразу Raspberry Pi 2, ведь там процессор Cortex, и там мой код уже работает у клиентов. Бинго. А если серьезно, то написание кода под микроконтроллеры это отдельная история с отдельным подходом к написанию кода, где многое чего не используется из стандарта, и много чего платформозависимо. Без разницы будь то Rust, C++ или что еще. И сдается мне, ты лично на Rust под микроконтроллеры не пишешь.

Мою точную цитату

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

Кстати о гарантиях:

~$ cat ./test.rs
fn main() {
    const SIZE: usize = 1024 * 1024;
    Box::new([10.0; SIZE]);
}
~$ rustc ./test.rs
~$ ./test 
Segmentation fault
~$ rustc -V
rustc 1.6.0

Это ведь просто гарантию не предоставили, а так Rust безопасный, да?

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

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

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

Ну ты скажи, что конкретно не так.

Да, блин, того проекта под руками нет (на рабочей машине), где я пытался на Расте запилить одну фигню. Типа делаем как белые люди - лепим интерфейсы сервисов, складываем их в манагер сервисов и они потом там друг дружку ищут по имени и друг друга вызывают. Потом потыкался по форумам, где на правильном английском разъяснялось, что ООП фишки до Раст 2.0 пока можно не ждать.

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

Аргумент - огонь. Типа: а если классов штук 100, это что каждому виртуальные функции оверрайдить придётся?

Конкретно для данного примера в нормальных языках - нет:

class T {
    func foo() {
        print( "\(self.dynamicType)")
    }    
}

class A : T {}
class B : T {}
class C : T {}

A().foo()
B().foo()
C().foo()
anonymous
()
Ответ на: комментарий от tailgunner

Макрос напиши. Нашел проблему на ровном месте, как с Option<Box<>>.

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

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

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

Лорчую. Как и любой Ядерный код, кстати.

Это ведь просто гарантию не предоставили, а так Rust безопасный, да?

Гарантию отменили во вине пользователя.

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

Конкретно для данного примера в нормальных языках - нет

Конкретно такие примеры нормальные люди обычно не пишут.

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

Огромным оно перестает быть очень быстро, со временем становится всё меньше и меньше, и вылезают реально важные вещи.

При прочих равных

Прочие всегда не равны.

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

Огромным оно перестает быть очень быстро, со временем становится всё меньше и меньше, и вылезают реально важные вещи.
Прочие всегда не равны.

Это уже в чистом виде казуистика.

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

А если типов штук 100? на каждый придется импиметацию писать?

Так если у тебя 100 типов, которые реализуют интерфейс, то реализацию ты не пишешь что ли?

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

Это ведь просто гарантию не предоставили, а так Rust безопасный, да?

Без оптимизаций, компилятор генерирует то, что ты написал. А написал ты следующее, выдели массив 8 Мб на стеке, заполни его значениями 10.0, выдели 8 Мб в куче, скопируй массив в кучу. Естественно ядро сказало, что ты дурак, и не дало тебе столько места под стек.

С оптимизациями, работы со стеком не будет, а будет 8 Мб в куче и заполнить их 10.0.

Всё по правилам.

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

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

Естественно:

let mut vec: Vec<Box<T>> = Vec::new();
vec.push(Box::new(A));
vec.push(Box::new(B));
vec.push(Box::new(C));
// ...
Ну и ты же понимаешь, что к трeйтам/интерфейсам это вообще отношения не имеет?

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

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

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

И сдается мне, ты лично на Rust под микроконтроллеры не пишешь.

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

Это ведь просто гарантию не предоставили, а так Rust безопасный, да?

Какое отношение баг в компиляторе имеет к безопасности языка?

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

Не, я слышал, что даже на Джавах ядра писали

На шарпе же!

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

Конкретно для данного примера в нормальных языках - нет:

И как часто нужно именно такое? Ты же понимаешь, что пример просто для иллюстрации?

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

Переходите на новый мейнстримовый язык — Rust.
мейнстримовый

Смишно, да.

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

Ну и ты же понимаешь, что к трeйтам/интерфейсам это вообще отношения не имеет?

Ну-ну, я от компилятора таких ругательств наслушался - хорошо хоть дети не слышали. Пока ты работаешь с обычными структурами и типами - все отлично, но как только ты касаешься трейетов - то объяви его унаследованным от Sized ибо у него размера нет, то добавь Sync ибо еще какая-то лажа.
P.S.В среду выйду на работу и, если не забуду, покажу этот кизяк.

void_ptr ★★★★
()
Ответ на: комментарий от anonymous
#![feature(core_intrinsics)]

trait Bar {
    fn foo(&self) {
        let type_name = unsafe {
            std::intrinsics::type_name::<Self>()
        };
        println!("{}", &type_name);
    }
}

struct A;
struct B;
struct C;

impl Bar for A{}
impl Bar for B{}
impl Bar for C{}

fn main() {
    A{}.foo();
    B{}.foo();
    C{}.foo();
}
A
B
C
anonymous
()
Ответ на: комментарий от DarkEld3r

И как часто нужно именно такое? Ты же понимаешь, что пример просто для иллюстрации?

Ес-но пример для иллюстрации, а вот рефлексия, например, в Java это то, что используется во все поля.

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

И еще на тему рефакторинга:

Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте
(c) Стив Макконел/Мартин Голдинг

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

Пока ты работаешь с обычными структурами и типами - все отлично, но как только ты касаешься трейетов - то объяви его унаследованным от Sized ибо у него размера нет, то добавь Sync ибо еще какая-то лажа.

Подозреваю, что всё исправило банальное оборачивание в Box. В этом плане раст ведёт себя вполне логично, хотя и, возможно, несколько непривычно.

P.S.В среду выйду на работу и, если не забуду, покажу этот кизяк.

Ок, на тему подписан, так что не пропущу. Взглянуть будет интересно.

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