Новость из категории: Информация

Язык программирования Rust: исключения и общие выводы

Содержание:
1. История и установка;
2. Утилиты, документация, идеология и синтаксис;
3. Переменные, указатели, массивы и функции;
4. Объектно-ориентированное программирование;
5. Исключения и общие выводы (Вы читаете данный раздел).
Исключения

Язык программирования Rust: исключения и общие выводы

В Rust применяется необычная система работы с исключениями. Вызов макроса fail! (~строка) или конструкции assert! порождает исключение и приводит к откату стека вызовов, принудительному вызову деструкторов объектов, освобождению памяти и завершению текущего потока. Перехватить исключение внутри потока невозможно: возникнув, оно всегда приводит к его остановке, но можно обработать исключение в родительском потоке. Для этого существует довольно запутанная комбинация из функции try и вариантов вызова spawn, spawn_supervised и spawn_unlinked. Идея в том, что по умолчанию (spawn) исключения дочерних потоков пере-даются в родительский и убивают его. При вызове spawn_supervised родительский поток может обработать исключение и продолжить выполнение. При вызове spawn_unlinked исключение вообще не передается родителю (поток полностью изолирован). Функция try применяется достаточно хитроумно - ее надо указать при порождении потока:
let result: Result = do task::try {
if some_condition() {
calculate_result()
} else {
// Выбрасываем исключение
fail!(~"oops!");
}
};
// Ловим исключение и печатаем информацию о нем
assert!(result.is_err());

Механизм работы с исключениями в Rust показался мне слишком запутанным и не интуитивным. Возможно, это дело привычки, но в большинстве других языков исключения работают иначе, что серьезно увеличивает «барьер вхождения».

Макросы

В Rust имеется возможность генерации кода во время компиляции с помощью синтаксических макросов. В коде программы макросы легко опознать по суффиксу «!» после их имени. При беглом ознакомлении язык макросов по сложности и запутанности может составить достойную конкуренцию «шаблонной магии» в С++. С помощью макросов, в частности, реализованы инструкции fmt! и assert!.

Модули и клети

Понятие модулей знакомо любому, кто работал с языками Python или Pascal. Оно интуитивно понятно и означает некую отдельную область видимости для символов, которую можно импортировать в текущий контекст и использовать. Каждый отдельный файл в Rust становится одноименным модулем. Кроме того, модули можно создавать ключевым словом mod:
mod farm {
pub fn chicken() -> &str { "Чирик-чирик!" }
priv fn cow() -> &str { "Мууу!" }
}

Ключевые слова priv и pub определяют область видимости символов при импорте модуля. По умолчанию все символы публично доступны. Импорт осуществляется при помощи ключевого слова use:
use farm::chicken;

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

В Rust есть также необычное понятие «клеть» (crate). Клеть - это независимая единица компиляции и компоновки, т.е. финальный исполнимый бинарный файл либо библиотека. Клеть может получаться путем компиляции множества исходных файлов и компоновки с внешними библиотеками. В Rust компиляция и сборка клетей описываются средствами самого языка без внешних систем сборки (таких как autotools, CMake или Scons). Для этого используются специальные файлы клетей с расширением rc. По сути, эти файлы - аналоги знакомых всем make-файлов. В них описываются опции компиляции и зависимости:
// Метаданные для компоновщика
#[link(name = "farm", vers = "2.5", author = "mjh")];
// Указываем, что нам нужна библиотека, а не исполняемый файл
#[crate_type = "lib"];
// Можно передать компилятору различные опции - например, потребовать вывод
// предупреждений
#[warn(non_camel_case_types)]
// Компоновать со стандартной библиотекой
extern mod std;
// Найти исходники указанных модулей и скомпилировать их mod cow; mod chicken; mod horse;
fn main() {

}

При поиске модулей используется интересная схема, в которой вложенность модулей в rc-файле соответствует их иерархии в файловой системе. Например, такое объявление:
mod shape {
mod square; mod triangle;
}

приведет к поиску файлов shape/square.rs и shape/triangle.rs.

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

Стандартная библиотека

Стандартная библиотека языка Rust не особенно впечатляет на фоне огромных библиотек С# или Java. Тем не менее, в нее входят 49 модулей разной степени полезности и готовности. Документация ко многим модулям ограничивается автоматически сгенерированными аннотациями и зачастую даже не дает возможности понять, что делает модуль - особенно это касается утилит низкого уровня. Наиболее интересны и полезны следующие модули:
> bigint - поддержка целых чисел произвольного размера;
> deque - круговой буфер;
> dlist - двусвязные списки;
> treemap, fun_treemap - ассоциативные контейнеры;
> getopts - упрощенная альтернатива библиотеки getopt;
> json - работа с данными в формате json;
> net_ip, net_tcp, net_url - работа с соответствующими сетевыми протоколами;
> sha1 - криптографический алгоритм shal;
> sort - методы сортировки.

Строгости и системности в построении стандартной библиотеки не прослеживается, но, возможно, это связано с тем, что она еще очень далека от готовности.

Кому нужен Rust?

Попробуем разобраться, кому нужен такой язык, как Rust, и на что он может претендовать в будущем. Начнем с объективных «технических характеристик» языка. Rust - это «нативно» компилируемый, строго типизированный, мультипарадигменный язык со встроенной многопоточ-ностью и управлением памятью, бинарно совместимый с Си, который призван быть проще С++ в написании и отладке и позиционируется как замена С++ в масштабных проектах. До появления Rust в этой нише уже успешно существовали два языка, которые в той или иной степени дублируют функциональность Rust: Go и D. Вместо того, чтобы использовать один из них, или просто ограничится каким-то фреймворком для С++, в Mozilla пошли по пути изобретения велосипеда.

Язык программирования Rust: исключения и общие выводы

По идеологии Rust гораздо ближе к Go, но нетрудно догадаться, почему Mozilla не стала использовать этот язык: Go разрабатывается в Google, т.е. у идейных конкурентов на рынке браузеров и мобильных операционных систем. Язык не стандартизирован, а сторонние реализации ненадежны. Кроме того, Go не очень приспособлен для разработки браузерного движка - это все-таки язык, созданный для серверной части веб-сервисов...
Гораздо труднее понять, что не устроило Mozilla в языке D. D - достаточно зрелый язык с готовыми свободными компиляторами. В D есть абсолютно все, что вошло в Rust, и многое другое. Чтобы убедиться в этом, достаточно выписать основные «фишки» обоих языков:

Мне не удалось найти в Rust ничего, чего не было бы в D, кроме чисто синтаксических различий и различных вариантов реализации одних и тех же идей. Напрашивается неутешительный вывод, что в просто Mozilla сработал печально известный принцип «изобретено не здесь». Если копнуть немного глубже, то становится заметна интересная тенденция. Каждая компания, которая претендует на свой сегмент растущего как на дрожжах рынка мобильных устройств, стремится создать не только свою операционную систему, но и свои языки программирования. У Microsoft есть .NET с C#, у Apple - Objective C, у Google - Go для серверов и Dart для клиентов. Ubuntu и Samsung делают ставку на Qt и QML, которые хоть и не разработаны ими лично, но не используются конкурентами. Теперь и Mozilla запускает Rust как язык, на котором будет написано следующее поколение браузеров для Firefox OS.

Язык программирования Rust: исключения и общие выводы
Сравнение основных «фишек» языков

Таким образом, Rust - это скорее стратегический и маркетинговый ход, чем необходимость. В обозримом будущем язык, по-видимому, не выйдет за пределы инфраструктуры Firefox OS. Учитывая, что сама система Firefox OS еще толком не появилась на реальных устройствах и ее коммерческий успех остается сомнительным, то будущее Rust выглядит, мягко говоря, туманно.

Появление новых языков программирования, вызванных к жизни исключительно соображениями безопасности инвестиций, имиджа и маркетинга, на мой взгляд, является негативным явлением. Кроме распыления усилий немногочисленных грамотных разработчиков компиляторов это создает нешуточные проблемы для прикладных программистов. «Внутренности» каждой из систем оказываются скрыты за барьером незнакомого языка, а взаимное заимствование кода оказывается сильно затрудненным. Это идет вразрез с самой идеей свободного ПО.

Получается, что формально система открыта, а на практике от этого довольно мало проку, поскольку код на Go нельзя позаимствовать для системы, написанной на Rust или Qt. Вместо унификации и взаимопомощи для блага пользователя в очередной раз начинается «дробление мощностей», дублирование усилий и нарастание несовместимости.

Mozilla уже имеет одну технологию, которая не используется нигде кроме ее продуктов, - это XUL, на котором базируется интерфейс Firefox и Thunderbird. Теперь к ней добавился Rust - язык, созданный исключительно для внутренних нужд Mozilla из-за того, что все остальное «изобретено не здесь». На мой взгляд Rust попросту не нужен, но окончательный ответ на этот вопрос даст время и рыночная конъюнктура.

Рейтинг статьи

Оценка
3/5
голосов: 3
Ваша оценка статье по пятибальной шкале:
 
 
   

Поделиться

Похожие новости

Комментарии

^ Наверх