Что такое rust alpha
Куча людей посмотрели это видео уже давно, подключайся и смотри первым!
Ранний доступ. Как много самых разных эмоций вызывает это словосочетание. У одних оно ассоциируется с уникальным геймплеем, который невозможно встретить в играх высокого калибра, другие считают данный раздел в Steam воровством и попрошайничеством. Но невозможно отрицать факт – ранний доступ плотно въелся в игровую индустрию и дал многим разработчикам шанс реализовать себя.
Доброго времени суток, в этот час мы рады представить новую рубрику под названием «Как изменялись игры», в пилотом выпуске мы рассмотрим игру Rust.
Находясь уже почти два года на рынке в раннем доступе, игра привлекла к себе огромное число игроков, а если быть точнее, то около 3 миллионов. Вкратце напомню, что за игра перед нами. В Rust необходимо выживать на неблагоприятной территории, вас может погубить огромное число причин, среди них: кровожадные животные, не менее опасные игроки, голод, обморожение и другие.
Наверняка, многие не знают, что было раньше, года полтора назад. За всё время существования на рынке игра один раз кардинально изменилась, пересев на новые «рельсы». Были интегрированы некоторые функции сервиса Steam и ещё очень много разностей было добавлено.
Но давайте не будем торопиться и двинемся на несколько лет назад, в 2013 год.
Примерно в марте появилась система голода и радиации. В июне мы уже можем заметить значительные изменения в интерфейсе, которые остались с нами до «перерождения» игры.
В итоге за тот промежуток времени игра неплохо преобразилась и 11 декабря 2013 года игра вышла в сервисе Steam. В той версии уже присутствовал основной костяк особенностей, которые и остаются с нами и по сей день: строительство домов разных форм и размеров, охота на зверей и людей. К выходу был подготовлен достаточно весёлый трейлер.
Произошло значительное изменение, из игры полностью вырезали зомби, поэтому они сместили акцент с выживания в зомби-апокалипсисе на выживание в суровом, неблагоприятном мире, где тебя окружают волки, медведи и кабаны. Добавили кровать, револьвер, оптимизировали небо, которое любило «отъедать» ваши кадры в секунду.
В это время разработчики начали разрабатывать новую версию Rust на более современной версии Unity (потому что предшественник не мог воплотить многие аспекты в жизнь), создавая заново интерфейс, графику и остальное.
В первую очередь старались улучшить инвентарь и интерфейс, появились более удобные всплывающие окошки при выборе действия, чтобы, например, зажечь костёр. Дальше появилась нормальная модель человека. Вообще изначально вместо людей на сервере «бегали» прямоугольники.
Персонажи научились «спать», добавлена возможность переключится на третье лицо. Игра научилась генерировать карты с различным ландшафтом, естественно на очень примитивном уровне, но со временем получалась менее «картонная», но зато более насыщенная местность.
На самом деле за май было сделано гораздо больше, чем описано выше. Давайте просто вкратце перечислю многие функции, которые добавляли за то время: добавлены и улучшены новые анимации, переделан голосовой чат, появилась смена настроек графики без нужды выхода в главное меню.
В основном, в первую половину месяца работали над новой системой постройки зданий. Было несколько вариантов, как реализовать эту возможность, но остановились на том, что с помощью молотка можно устанавливать разные части строения. До конца доделали интерфейс, который оставался с нами до поры до времени, пытались интегрировать пещеры в мир игры, много графических улучшений, таких как: новая трава, звезды, анимации у волков, улучшенный биом «лес».
Создана очень важная функция, именуемая «метаболизм». Она совмещает в себе разные эффекты, в неё входят: сердцебиение, голод и жажда, кровотечение, запас кислорода и влажность.
Был добавлен лук, факел (странно, что его не было в самом начале), новый «снежный» биом, теперь вещи могут показывать различные показатели защиты от холода, радиации, пуль и подобного.
Улучшены модели персонажей в том плане, что они теперь лучше реагируют на источники освещения, появилось больше различных теней и оттенков. Изменена система глобального освещения мира, так как можно было обнаружить «мерцания» поверхности. К животным был «прикручен» мех, который, кстати, можно очень просто применять и на других моделях, как, например, на этом товарище.
Уже в который раз улучшили систему генерации мира, в этот раз добавили «монументы» – огромные постройки и статуи, которые служат в качестве неких ориентиров.
Но главным изменением стал переход на 5-ую версию Unity. Как объяснили разработчики, это дало значительный прирост эффективности, так как многие ограничения прошлых версий были сняты, да и многие действия были упрощены. Но это событие повлекло проблемы, к примеру, сломался голосовой чат, интерфейс попросту глючил.
Разработчики представили концепт зданий, состоящих не только из одних квадратов. Такие здания выглядят элегантнее, достаточно просто взглянуть на данный макет:
Большая часть времени была посвящена устранению багов и борьбой с Unity 5, так как программа всё ещё находилась в бета-тесте. Но и за это время появились и обдумывались новые интересные вещи. Самое банальное из всего списка – 3 инструмента и копьё. Ещё появился кодовый замок в качестве отдельного предмета, так как многих система с ключами бесила.
Из интересного: появлялись мысли на подобии «А что если мы…». Темой размышлений стала торговля чертежами. Разработчик хотел внедрить такую систему, которая позволяет «зарабатывать» чертежи во время игры (почти как шапки из TF2). А после, если есть нужда, продавать их либо обмениваться с вашими друзьями. Но до реализации (к счастью) руки не дошли.
Темой ноября может полноценно стать «Изменение системы строительства». Появилось много функций, сильно повлиявших на геймплей в целом:
Вернулся Radtown из оригинала. Суть его не изменилась: много лута + радиация. В первых версиях много экспериментировали, как и где должны стоять нужные строения. Ещё появились бочки, которые можно совершенно случайно обнаружить, например, в поле, и в них тоже лежит лут разной степени редкости.
Уже не помню, в который раз это пишу, но снова обновили генерацию местности, теперь появились реки, что дало больше разнообразия. Добавили таблички, на которых можно писать разные фразы. Теперь игроки получают «уникальную» внешность, но, разумеется, не самую разнообразную – есть только 2 формы лица и 2 текстуры кожи. Понятное дело, выбор не велик, но эту проблему достаточно быстро поправили.
Месяц добавления всего и вся. Самые разные вещи были введены: баррикады, гитара, лошадь, новые типы лестниц, ракетница, рисованные иконки для вещей. Теперь на табличках можно рисовать (да здравствуют половые органы и маты!). Сделали целую карту вручную, которая похожа на Legacy-версию. Убрали такую особенность, когда вещи выбрасываются в мешочках, теперь они имеют собственные модельки.
Этот месяц стал одним из самых насыщенных в истории. Добавили 5 экземпляров двуручного оружия, вдобавок ещё арбалет и мины. Ещё вы можете поверх своей одежды надевать подобие бронежилетов, например, из дорожных знаков.
Можно качать нефть с помощью наносной станции, принцип тот же, как и у сборщика руды. Чтобы не ставить очень много маленьких печей, была введена большая печь – переплавляет вещи быстрее, да и слотов стало больше.
Была полностью переработана система чертежей. Дело в том, что раньше нужно было надеяться на свою удачу, вам может выпасть нужный чертёж в первые минуты игры или не выпасть даже через несколько часов. Теперь падают фрагменты чертежей, отличающиеся по степени редкости. Собрав n-ое число, можно получить случайный рецепт.
Для разнообразия Radtown’ов разработали, но пока ещё не добавили, так называемые «подземелья». Первым на очереди стала водоочистная станция, она поделена на несколько уровней и содержит в себе достаточно ценный лут.
Разработчики чутка «сломали» игру одним патчем, поэтому много времени уделили на хотфиксы и оптимизацию игры в целом. Для начинающих игроков был добавлен тайник, который можно «закапывать» от других игроков. Защитники получили себе в арсенал турели – они очень редкие, так как основные ресурсы добываются только с вертолёта.
Привнесли 13 новых табличек и разных баннеров. Ещё ваш персонаж научился метать разные предметы: камни, топоры и подобное.
Пока я ковырялся с видео версией, практически полностью закончился ноябрь, но и его тоже возьмём в расчет.
Появились оконные ставни и металлические амбразуры. Теперь с вертолётов можно снимать М249. Также полностью вырезали нефтедобывающие станции. Причина проста – разработчики ввели их слишком рано.
Примерно такой путь прошел Rust за пару лет существования. От обычной «браузерки» до одной из самых популярных выживалок на рынке. Конечно, здесь расписаны только основные нововведения, в обход технической части.
Но это не главное. Цель новой рубрики – показать, что происходит с игрой в разделе «Ранний доступ». Rust является очень хорошим примером, потому что разницу между версией декабря 2013 года и нынешней видно невооруженным глазом.
Ну, а напоследок, вопросы. Понравилась ли вам эта рубрика, что изменить в ней и какую игру вы хотите увидеть в следующих частях? Ведь было затрачено много человеко-часов, поэтому с достоинством подойдите к оценке.
Rust Alpha
Не следил активно за изменениями, но в своё время прочёл уже устаревшую Rust by Example и туториалы с официального сайта. Теперь вот начал неспешно читать новую «книгу», которая заменила собой старые гайды. Но некоторые моменты вызывают удивление. Знаю, что тут есть пару человек, которые в языке неплохо разбираются, так что может обьяснят почему сделали именно так.
1. Функции высшего порядка. Старый вариант:
That is because in Rust each closure has its own unique type. So, not only do closures with different signatures have different types, but different closures with the same signature have different types, as well!
По моему, они взяли худшее из обоих вариантов. Есть в этом какой-то смысл?
Опять же where тут, в отличии от хаскеля, выглядит коряво. Мы и так сначала заявляем, что вот у нас есть типы ( ), потом ещё раз про них говорим (f: F, g: G) и наконец-то определяем их. Я бы ещё понял, если бы where позволяло отказаться от указания типов в угловых скобках.
В книге этот момент не поясняется, но всюду используется вариант |&:|. Раньше в гайдах писали просто ||. Правильно понимаю, что можно задавать как будут захватываться переменные? А на уровне отдельных переменных можно?
3. Named arguments, variable arguments.
В описании методов присутствует следующее:
Rust doesn’t have method overloading, named arguments, or variable arguments. We employ the builder pattern instead.
tailgunner
ozkriff
numas13
Мне кажется, в 1 у тебя конструкции разного назначения. Может:
Раньше в гайдах писали просто ||. Правильно понимаю, что можно задавать как будут захватываться переменные?
А на уровне отдельных переменных можно?
Думаю, нет. Да и зачем?
мда, а так все хорошо начиналось :-/
В книге этот момент не поясняется, но всюду используется вариант |&:|
Обычно можно использовать и ||, компилятор сам выведет что именно нужно.
В Rust функции высшего порядка = замыкания, отсюда все нюансы описания прототипов функций.
в этом языке термин «синтаксический сахар» заменен на «синтаксический кал»
Лет через N все будут удивляться, мол, всё же было продумано, а получилось гогно.
Анонимные эксперты, как всегда, на высоте!
Мне кажется, в 1 у тебя конструкции разного назначения. Может:
Так сходу не скажу надо ли оно. После С++ привык к большей гибкости и к тому, чтобы явно прописывать, что захватывать, во избежание сюрпризов. Впрочем, может система типов раста и не даст выстрелить в ногу.
Хорошо если так. Вообще создалось впечатление, что гайды они спешно и криво в «книгу» переделали и многие примеры стали хуже. В смысле, много мелочей не относящихся к демонстрируемым идеям.
Лет через N все будут удивляться, мол, всё же было продумано, а получилось гогно.
Это не совсем справедливо. Я хоть и был настроен изначально весьма скептически, но часто, со временем, понимаешь, что сделали в итоге правильно, пусть и пришлось чем-то пожертвовать.
Кстати, ещё один момент. Раньше, если ничего не путаю, для «числовых констант» надо было указывать тип (если он, конечно, не мог быть выведен):
В Rust функции высшего порядка = замыкания, отсюда все нюансы описания прототипов функций.
Это ничего не объясняет. Как раз в старом варианте было точно как ты говоришь: объявление замыканий и «параметров функций» выглядело одинаково. Теперь нет.
Есть два принципиально разных вида замыканий: boxed и unboxed.
Много раз встречал упоминание этого, но прочитанные мануалы как-то не раскрывали тему. Вот сейчас нагуглил:
Short version: current closures in Rust are «boxed» in that they consist of a function pointer, and a pointer to the closure environment (which contains captured variables). LLVM has trouble inlining and optimising around these indirections.
Unboxed closures work by having each closure expand to an anonymous type which is effectively a struct that contains the captured variables, and implements one of the three kinds of «call» operator. Because there’s no indirection involved, LLVM can much more easily inline and optimise these calls.
Eventually, it won’t be unboxed vs. boxed closures, there will just be unboxed closures and everything will be puppies and unicorns.
Если всё так и осталось, а не устарело, то это просто детали реализации? И непонятно зачем они торчат наружу, если от них потом всё равно собираются избавиться. Смысл тогда придумывать новые синтаксисы.
как будет использоваться замыкание: лишь один раз, много раз
Про это в курсе. Раньше было proc(), теперь стало move перед обьявлением замыкания.
с изменяемым окружением или неизменяемым.
Это в смысле, |&:| и |&mut:| или как-то иначе?
Ну теоретически, может захотеться, что-то по мутаблеьной ссылке захватить, а что-то по значению.
Если всё так и осталось, а не устарело, то это просто детали реализации?
Не просто. Прочти внимательно вот это: http://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/
Так как размер замыкания заранее неизвестен (так как неизвестен размер окружения), для статической диспечеризации нужна мономорфизация. Но в то же время это позволяет функциям вроде map обходиться без косвенной адресации и не уступать циклам в производительности.
Если же требуется большая гибкость, используются boxed замыкания. Они подразумевают косвенную адресацию, но мономорфизации не требуют.
Про это в курсе. Раньше было proc(), теперь стало move перед обьявлением замыкания.
Неверно. move задаёт то, как захватывается окружение, а не то, как его потом используют.
FnOnce, Fn и FnMut. Им соответствуют |:|, |&:| и |&mut:|.
Не стоит забывать, что раст — системный язык, поэтому в нём уделяется внимание тому, чему обычно не уделяют внимания в несистемных языках.
Вот простой пример: http://is.gd/dscH76. Замыкание используется несколько раз, но строка `s` перемещена из `main` в замыкание.
Мне кажется, в 1 у тебя конструкции разного назначения. Может:
Вроде же move убрали давно, нет?
Я неправильно выразился, все лямбды = замыкания.
С чего бы? Вот пример его использования: http://doc.rust-lang.org/std/thread/index.html
Да, перемещение переменных в замыкание нужно не всегда, но всё же иногда требуется.
Ты откопал что-то ОЧЕНЬ древнее, где move имеет совсем другое значение.
Не перестаю охреневать от синтаксиса. Он по набору магических символов и нечитаемости скоро перл перегонит.
RUST (Alpha) — [RUS] Server net.connect 109.95.211.219:29615
RUST это игра на выживание, созданная Facepunch Studios. Много чего взято из таких игр, как DayZ, Minecraft и Stalker — игра RUST нацелена, чтобы создать вокруг игрока полную неожиданностей враждебную среду.
Существует две основных опасности в игре.
Очень полезные ссылки:
Сервер расположен на специальном хостинге для игровых серверов, политика разработчиков не позволяет свободно распространять серверное по для игры RUST, вследствие этого установлен жесткий контроль на официальных серверах в виде античитов и проверки лицензии на копию игры через Steam-аккаунты. Нарушители правил будут блокироваться сразу на всех серверах RUST. Также достаточно ограничены возможности администрирования.
Как зайти на сервер #1:
— Нажать на F1 (откроется консоль)
— Скопировать туда net.connect 109.95.211.219:29615
— Нажать Enter
Публичная страница сервера: http://vk.com/rustsrv — вся оперативная информация о проблемах и новостях сервера игроки подписывайтесь чтобы быть в курсе.
На сервере планируется система PvP и PvE
PvP в основном включается вечером
График будет в будущем меняться!)
Разработчики сервера не предоставили инструментов автоматизации управления конфигурацией по расписанию, по этой причине переключение режимов PvP и PvE происходит вручную и зависит от присутствия администратора в онлайне.
то как должна теоретически работать система PvP/PvE представлено на форуме одного из зарубежных кланов RUST: http://facepunch.com/showthread.php?t=1323414
Ниже в комментариях отзывы о сервере, Ваши пожелания и предложения.
Если вы застряли пишите ник в игре.
Обзор языка программирования Rust
Rust — новый экспериментальный язык программирования, разрабатываемый Mozilla. Язык компилируемый и мультипарадигмальный, позиционируется как альтернатива С/С++, что уже само по себе интересно, так как даже претендентов на конкуренцию не так уж и много. Можно вспомнить D Вальтера Брайта или Go от Google.
В Rust поддерживаются функицональное, параллельное, процедурное и объектно-ориентированное программирование, т.е. почти весь спектр реально используемых в прикладном программировании парадигм.
Я не ставлю целью перевести документацию (к тому же она весьма скудная и постоянно изменяется, т.к. официального релиза языка еще не было), вместо этого хочется осветить наиболее интересные фичи языка. Информация собрана как из официальной документации, так и из крайне немногочисленных упоминаний языка на просторах Интернета.
Первое впечатление
Синтаксис языка строится в традиционном си-подобном стиле (что не может не радовать, так как это уже стандарт де-факто). Естественно, всем известные ошибки дизайна С/С++ учтены.
Традиционный Hello World выглядит так:
Пример чуть посложнее — функция расчета факториала:
Как видно из примера, функции объявляются в «функциональном» стиле (такой стиль имеет некоторые преимущества перед традиционным «int fac(int n)»). Видим автоматический вывод типов (ключевое слово let), отсутствие круглых скобок у аргумента while (аналогично Go). Еще сразу бросается в глаза компактность ключевых слов. Создатели Rust дейтсвительно целенаправленно сделали все ключевые слова как можно более короткими, и, скажу честно, мне это нравится.
Мелкие, но интересные синтаксические особенности
Типы данных
Rust, подобно Go, поддерживает структурную типизацию (хотя, по утверждению авторов, языки развивались независимо, так что это влияние их общих предшественников — Alef, Limbo и т.д.). Что такое структурная типизация? Например, у вас в каком-то файле объявлена структура (или, в терминологии Rust, «запись»)
type point =
Вы можете объявить кучу переменных и функций с типами аргументов «point». Затем, где-нибудь в другом месте, вы можете объявить какую-нибудь другую структуру, например
type MySuperPoint =
и переменные этого типа будут полностью совместимы с переменными типа point.
В противоположность этому, номинативная типизация, принятая в С, С++,C# и Java таких конструкций не допускает. При номинативной типизации каждая структура — это уникальный тип, по умолчанию несовместимый с другими типами.
Структуры в Rust называются «записи» (record). Также имеются кортежи — это те же записи, но с безымянными полями. Элементы кортежа, в отличие от элементов записи, не могут быть изменяемыми.
Имеются вектора — в чем-то подобные обычным массивам, а в чем-то — типу std::vector из stl. При инициализации списком используются квадратные скобки, а не фигурные как в С/С++
Вектор, тем ни менее — динамическая структура данных, в частности, вектора поддерживают конкатенацию.
Есть шаблоны. Их синтаксис вполне логичен, без нагромождений «template» из С++. Поддерживаются шаблоны функций и типов данных.
Язык поддерживает так называемые теги. Это не что иное, как union из Си, с дополнительным полем — кодом используемого варианта (то есть нечто общее между объединением и перечислением). Или, с точки зрения теории — алгебраический тип данных.
В простейшем случае тег идентичен перечислению:
В более сложных случаях каждый элемент «перечисления» — самостоятельная структура, имеющая свой «конструктор».
Еще интересный пример — рекурсивная структура, с помощью которой задается объект типа «список»:
Теги могут участвовать в выражениях сопоставления с образцом, которые могут быть достаточно сложными.
Сопоставление с образцом (pattern matching)
Для начала можно рассматривать паттерн матчинг как улучшенный switch. Используется ключевое слово alt, после которого следует анализируемое выражение, а затем в теле оператора — паттерны и действия в случае совпадения с паттернами.
В качестве «паттеронов» можно использовать не только константы (как в Си), но и более сложные выражения — переменные, кортежи, диапазоны, типы, символы-заполнители (placeholders, ‘_’). Можно прописывать дополнительные условия с помощью оператора when, следующего сразу за паттерном. Существует специальный вариант оператора для матчинга типов. Такое возможно, поскольку в языке присутствует универсальный вариантный тип any, объекты которого могут содержать значения любого типа.
Указатели. Кроме обычных «сишных» указателей, в Rust поддерживаются специальные «умные» указатели со встроенным подсчетом ссылок — разделяемые (Shared boxes) и уникальные (Unique boxes). Они в чем-то подобны shared_ptr и unique_ptr из С++. Они имеют свой синтаксис: @ для разделяемых и
для уникальных. Для уникальных указателей вместо копирования существует специальная операция — перемещение:
после такого перемещения указатель x деинициализируется.
Замыкания, частичное применение, итераторы
С этого места начинается функциональное программирование. В Rust полностью поддерживается концепция функций высшего порядка — то есть функций, которые могут принимать в качестве своих аргументов и возвращать другие функции.
1. Ключевое слово lambda используется для объявления вложенной функции или функционального типа данных.
В этом примере мы имеем функцию make_plus_function, принимающую один аргумент «x» типа int и возвращающую функцию типа «int->int» (здесь lambda — ключевое слово). В теле функции описывается эта самая фунция. Немного сбивает с толку отсутствие оператора «return», впрочем, для ФП это обычное дело.
2. Ключевое слово block используется для объявления функционального типа — аргумента функции, в качестве которого можно подставить нечто, похожее на блок обычного кода.
Здесь мы имеем функцию, на вход которой подается блок — по сути лямбда-функция типа «int->int», и вектор типа int (о синтаксисе векторов далее). Сам «блок» в вызывающем коде записыавется с помощью несколько необычного синтаксиса <|x| x + 1 >. Лично мне больше нравятся лямбды в C#, символ | упорно воспринимается как битовое ИЛИ (которое, кстати, в Rust также есть, как и все старые добные сишные операции).
3. Частичное применение — это создание функции на основе другой функции с большим количеством аргументов путем указания значений некоторых аргументов этой другой функции. Для этого используется ключевое слово bind и символ-заполнитель «_»:
Чтобы было понятнее, скажу сразу, что такое можно сделать на обычном Си путем создания простейшей обертки, как-то так:
const char* daynum (int i) < const char *s =<"mo", "tu", "we", "do", "fr", "sa", "su">; return s[i]; >
Но частичное применение — это функциональный стиль, а не процедурный (кстати, из приведенного примера неясно, как сделать частичное применение, чтобы получить функцию без аргументов)
Еще пример: объявляется функция add с двумя аргументами int, возвращающая int. Далее объявляется функциональный тип single_param_fn, имеющий один аргумент int и возвращающий int. С помощью bind объявляются два функциональных объекта add4 и add5, построенные на основе функции add, у которой частично заданы аргументы.
Функциональные объекты можно вызывать также, как и обычные функции.
4. Чистые функции и предикаты
Чистые (pure) функции — это функции, не имеющие побочных эффектов (в том числе не вызывающие никаких других функций, кроме чистых). Такие функции выдяляются ключевым словом pure.
Предикаты — это чистые (pure) функции, возвращающие тип bool. Такие функции могут использоваться в системе typestate (см. дальше), то есть вызываться на этапе компиляции для различных статических проверок.
Синтаксические макросы
Планируемая фича, но очень полезная. В Rust она пока на стадии начальной разработки.
Выражение, аналогичное сишному printf, но выполняющееся во время компиляции (соответственно, все ошибки аргументов выявляются на стадии компиляции). К сожалению, материалов по синтаксическим макросам крайне мало, да и сами они находятся в стадии разработки, но есть надежда что получится что-то типа макросов Nemerle.
Кстати, в отличие от того же Nemerle, решение выделить макросы синтаксически с помощью символа # считаю очень грамотным: макрос — это сущность, очень сильно отличающаяся от функции, и я считаю важным с первого взгляда видеть, где в коде вызываются функции, а где — макросы.
Атрибуты
Концепция, похожая на атрибуты C# (и даже со схожим синтаксисом). За это разработчикам отдельное спасибо. Как и следовало ожидать, атрибуты добавляют метаинформацию к той сущности, которую они аннотируют,
Придуман еще один вариант синтаксиса атрибутов — та же строка, но с точкой с запятой в конце, аннотирует текущий контекст. То есть то, что соответствует ближайшим фигурным скобкам, охватывающим такой атрибут.
Параллельные вычисления
Пожалуй, одна из наиблее интересных частей языка. При этом в tutorial на данный момент не описана вообще:)
Программа на Rust состоит из «дерева задач». Каждая задача имеет функцию входа, собственный стек, средства взаимодействия с другими задачами — каналы для исходящей информации и порты для входящей, и владеет некоторой частью объектов в динамической куче.
Множество задач Rust могут существовать в рамках одного процесса операционной системы. Задачи Rust «легковесные»: каждая задача потребляет меньше памяти чем процесс ОС, и переключение между ними осуществляется быстрее чем переключение между процессами ОС (тут, вероятно, имеются в виду все-же «потоки»).
Задача состоит как минимум из одной функции без аргументов. Запуск задачи осуществляется с помощью функции spawn. Каждая задача может иметь каналы, с помощью которых она передает инфорацию другим задачам. Канал — это специальный шаблонный тип chan, параметризируемый типом данных канала. Например, chan — канал для передачи беззнаковых байтов.
Для передачи в канал используется функция send, первым аргументом которой является канал, а вторым — значение для передачи. Фактически эта функция помещает значение во внутренний буфер канала.
Для приема данных используются порты. Порт — это шаблонный тип port, параметризируемый типом данных порта: port — порт для приема беззнаковых байтов.
Для чтения из портов используется функция recv, аргументом которой является порт, а возвращаемым значением — данные из порта. Чтение блокирует задачу, т.е. если порт пуст, задача переходит в состояние ожидания до тех пор, пока другая задача не отправит на связанный с портом канал данные.
Связывание каналов с портами происходит очень просто — путем инициализации канала портом с помощью ключевого слова chan:
let reqport = port();
let reqchan = chan(reqport);
Несколько каналов могут быть подключены к одному порту, но не наоборот — один канал не может быть подключен одновременно к нескольким портам.
Typestate
Общепринятого перевода на русский понятия «typestate» я так и не нашел, поэтому буду называть это «состояния типов». Суть этой фичи в том, что кроме обычного контроля типов, принятого в статической типизации, возможны дополнительные контекстные проверки на этапе компиляции.
В том или ином виде состояния типов знакомы всем программистам — по сообщениям компилятора «переменная используется без инициализации». Компилятор определяет места, где переменная, в которую ни разу не было записи, используется для чтения, и выдает предупреждение. В более общем виде эта идея выглядит так: у каждого объекта есть набор состояний, которые он может принимать. В каждом состоянии для этого объекта определены допустимые и недопустимые операции. И компилятор может выполнять проверки — допустима ли конкретная операция над объектом в том или ином месте программы. Важно, что эти проверки выполняются на этапе компиляции.
Например, если у нас есть объект типа «файл», то у него может быть состояние «закрыт» и «открыт». И операция чтения из файла недопустима, если файл закрыт. В современных языках обычно функция чтения или бросает исключение, или возвращает код ошибки. Система состояний типов могла бы выявить такую ошибку на этапе компиляции — подобно тому, как компилятор определяет, что операция чтения переменной происходит до любой возможной операции записи, он мог бы определить, что метод «Read», допустимый в состоянии «файл открыт», вызывается до метода «Open», переводящего объект в это состояние.
В Rust существует понятие «предикаты» — специальные функции, не имеющие побочных эффектов и возвращающие тип bool. Такие функции могут использоваться компилятором для вызова на этапе компиляции с целью статических проверок тех или иных условий.
Ограничения (constraints) — это специальные проверки, которые могут выполняться на этапе компиляции. Для этого используется ключевое слово check.
Предикаты могут «навешиваться» на входные параметры функций таким вот способом:
Информации по typestate крайне мало, так что многие моменты пока непонятны, но концепция в любом случае интересная.
На этом все. Вполне возможно, что я все-же пропустил какие-то интересные моменты, но статья и так раздулась. При желании можно уже сейчас собрать компилятор Rust и попробовать поиграться с различными примерами. Информация по сборке приведена на официальном сайте языка.