Вышла новая версия языка Rust с номером 0.3. Несмотря на то, что говорить о каком бы то ни было коммерческом использовании языка рано, он обретает все более и более четкие формы, появляется понимание куда же он движется.
Автоматический вывод целочисленного типа
В Rust запрещено неявное преобразование между целочисленными типами, поэтому необходимо самостоятельно указывать соответствующий суффикс для всех типов кроме int, например 12_u8. Начиная с версии 0.3 данная система была доработана, и в большинстве ситуаций тип может быть выведен автоматически.
В данном случае мы получим массив восьмибитных беззнаковых целых. В случае использования сопоставления с образцом автоматический вывод типа так же актуален:
alt account_balance {
0 { log(error, "not enough") }
1 to 99 { log(error, "enough") }
_ { log(error, "whoa") }
}
Но, с учетом отсутствия неявного преобразования между типами, возможны конфликтные ситуации, например такие:
fn identity_u8(n: u8) -> u8 { n }
fn identity_u16(n: u16) -> u16 { n }
identity_u8(x); // после этого считается что `x` имеет тип `u8`
identity_u16(x); // неверный тип, ожидается `u16`, но найдено `u8`
Стабилизация классов и удаление ресурсов
Концепция ресурсов была признана нежизнеспособной и удалена, на ее замену пришли классы. На данный момент поддержка классов минимальна, тем не менее, имеется поддержка конструкторов, деструкоторов, реализация интерфейсов и поддержка параметризации.
fn speak();
}
iface printable {
fn print();
}
class talker<T: printable> : talky {
let word: T;
new(word: T) {
self.word = word;
}
drop {
self.speak();
}
fn speak() {
self.word.print();
}
}
Новый синтаксис замыканий, ключевое слово do
Замыкания получили более компактный синтаксис:
Они работают как с оператором for, так и в do выражениях, реализуя удобный синтаксический сахар для построения функций высшего порядка.
println(#fmt("%?", i));
}
При использовании замыканий без аргументов синтаксис еще проще:
// это тело замыкания
}
Использование ключевого слова do позволяет выносить функции высшего порядка за пределы списка аргументов.
do unpack_slice(rhs) |p, len| {
for range(0, len) |i| {
...
}
}
Новые типы массивов
До версии 0.3 массивы представляли собой уникальные объекты в куче, но случайное копирование и выделение памяти для массивов было серьезной угрозой для производительности.
Начиная с версии 0.3 массивы получили полную поддержку модели памяти Rust, таким образом, они могут быть расположены на стеке, в локальной памяти или глобальной памяти.
let x: ~[int] = ~[0];
// Разделяемый массив (shared vector), располагающийся в локальной памяти
let y: @[int] = @[0];
// Стековый массив (stack vector), располагающийся на стеке
let z: &[int] = &[0];
Внимание: на данный момент не все библиотечные функции поддерживают работу с новыми типами массивов.
Паттерн *
В Rust появился новый синтаксис для игнорирования полей в сравнении с образцом:
i_could_match_like_this(_, _, _, _, _, _) {
}
but_would_rather_like_this(*) {
}
}
Doc комментарии
Добавлена поддержка doc комментариев. Как и в случае с другими атрибутами, doc комментарии имеют различную форму в зависимости от расположения.
fn f() {
/// Альтернативная форма внешнего doc комментария
fn g() { }
fn h() {
/*! Внутренний doc комментарий */
}
fn i() {
//! Альтернативная форма внутренего doc комментария
}
Управление ошибками и предупреждениями компилятора отдельно для каждого элемента
Теперь предупреждения могут быть заблокированы не только на уровне crate (как это перевести?), как это было раньше, но и отдельно для каждой функции.
fn implicitly() -> ~[str] {
import std::sort::merge_sort;
merge_sort(str::eq, ~["not_implicitly_copyable"])
}
В данном примере merge_sort будет копировать элементы массива в процессе сортировки, в то же время строка не может быть копирована без задания типа copy (т.к. строки уникальны и их копирование приводит к выделению памяти). В такой ситуации компилятор Rust выдает предупреждение. Так как на данный момент нет механизма уровня языка для разрешения копированя, иногда необходимо просто подавить предупреждение компилятора.
Внимание: текущий синтаксис отключения предупреждений, использующий префикс “no_” с именем предупреждения, вводит в заблуждение и будет изменен в будущем.
Предупреждения (и их настройки по умолчанию), поддерживаемые компилятором Rust:
- ctypes (warn) – внешние модули должны использовать core::libc типы;
- unused_imports (ignore) – запретить импортирование неиспользующихся модулей;
- while_true (warn) – запретить использование while true (необходимо использовать оператор loop);
- path_statement (warn) – writing a statement that names a value without using it is usually a bug; (как это перевести?)
- old_vecs (warn) – использование устаревшего синтаксиса создания массивов ([], теперь используется для создания slice (как перевести???), а не для создания уникальных массивов. Текущий синтаксис для создания уникального массива ~[]);
- old_strs (ignore) – использование устревшего синтаксиса для создания строк
unrecognized_warning.
Приведенные ниже предупреждения относятся к процессу удаления дорогих операций неявного копирования. В соответствии с текущими правилами, типы, требующие выделения памяти при копировании (unique boxes (как это перевести?)) или содержащие изменяемые поля, не могут копироваться неявно. На данный момент это предупреждения компилятора, которые в дальнейшем будут повышены до ошибок, либо подобный код будет запрещен системой типов Rust по умолчанию.
- implicit_copys – создание копии типа, не поддерживающего неявное копирование без использования ключевого слова copy;
- vecs_not_implicitly_copyable – тоже самое, только для векторов;
- non_implicitly_copyable_typarams – использование параметризуемых типов с copy параметрами для типов данных, неподдерживающих неявное копирование.
Расширения синтаксиса
// Информация о файле
println(#fmt("%?", #line()));
println(#fmt("%?", #col()));
println(#fmt("%?", #file()));
// Имя текущего модуля, если доступно
println(#fmt("%?", #mod()));
let x = 10, y = 15;
// Добавление выражения Rust в строку
println(#fmt("%?", #stringify[x + y]));
// Включение содержимого файла в качестве выражения Rust
println(#fmt("%?", #include("x_plus_y.rs")));
// Включение содержимого файла в качестве строки
println(#fmt("%?", #include_str("x_plus_y.rs")));
// Включение содержимого файла в качестве бинарного массива
println(#fmt("%?", #include_bin("x_plus_y.rs")));
Квалификатор const
В Rust добавлен новый квалификатор const, который может использоваться в качестве ограничения для типов параметров. Тип, который является const, может включать в себя только неизменяемые поля. Тип являющийся как const так и send хорошо подходит для использования в параллельных вычислениях с использованием разделяемой памяти, так как является не изменяемым и не может содержать локальных указателей (local box pointers).
Данный квалификатор используется в модуле core::arc, который реализует автоматический подсчет ссылок и является sendable типом инкапсулирующим const + send квалификаторы.
// unique vectors are const and send kinds
let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let arc_v = arc::arc(v);
let p = port();
let c = chan(p);
do task::spawn() {
let p = port();
c.send(chan(p));
let arc_v = p.recv();
let v = *arc::get::<~[int]>(&arc_v);
assert v[3] == 4;
};
let c = p.recv();
c.send(arc::clone(&arc_v));
assert (*arc::get(&arc_v))[2] == 3;
log(info, arc_v);
}
Интерфейс взаимодействия с внешними функциями
Ключевое слово ‘native’ было исключено из языка так как подразумевало что Rust не является нативным. Теперь для описания внешних модулей необходимо использовать ключевое слово extern.
Функции Rust вызываемые из внешнего нативного кода с использованием CDECL ABI, которые раньше описывались при помощи ключевого слова crust, теперь так же описываются ключевым словом extern.
do_some_crusty_stuff(user_data);
}
Доработка стандартной библиотеки
В рамках работы над версией 0.3 было добавлено несколько новых методов для базовых типов доступных по умолчанию. В общем случае методы предпочтительнее функций, т.к. появилось четкая концепция работы с self типом.
Так же в состав стандартной библиотеки был добавлен новый модуль time, поддерживаемый Эриком Трайзеларом.
// Преобразование в строку
println(time.strftime("%D/%M/%Y"));
// tm поддерживает различные преобразования
println(time.ctime()); // "Thu Jan 1 00:00:00 1970"
println(time.rfc822()); // "Thu Jan 1 00:00:00 1970"
println(time.rfc3339()); // "2012-02-22T07:53:18-07:00"
Из языка удалено
Ключевые слова be, prove, syntax были удаленны из языка Rust. Ключевое слово mutable трансформировалось в mut, cont переименовано в again. Так как ключевое слово bind имело очень много пересечений с другими формами замыканий, оно так же было удалено. Так как do циклы используются довольно активно, ключевое слово do повторно введено в язык. Тип ресурсы был удален в пользу деструкторов класса.
Выглядит интересно , но зачем “fn”, “iface” ?
На чем экономят ?
А почему нет? Компактнее программа, легче читать, код не замусориватся кучей длиннющих ключевых слов.
crate (как это перевести?) транслейт говорит “клеть”