Pull to refresh

Comments 11

Статья не очень по одной простой причине - не объясняется нормально синтаксис макросов. Нет примеров использования по каждому макросу в материале. Без всего этого статья для незнающего человека бесполезна. Вам может казаться что все просто и понятно, но для человека кто видит синтаксис впервые , увы, нет

Такое чувство что языки Rust и С++ соревнуются, у кого более непонятное и запутанное метапрограммирование. Между тем, синтаксические макросы сами по себе - простая концепция, и при правильной реализации достаточно одной единственной разновидности, а не четырех.

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

Увы, но не так-то просто эту самую единственную разновидность синтаксических макросов подружить с подсветкой синтаксиса в IDE и контекстными подсказками в ней же.

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

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

А макросы в Си - это вообще подстановка без выполнения кода при компиляции (т.е. чистая квазицитата). И как показывает практика, во многих случаях такие макросы более чем достаточны (другое дело что в Си они реализованы на лексическом, а не на синтаксическом уровне, отсюда они игнорируют структуру кода, области видимости, права доступа и т.п.). В Rust этому вроде как соответствуют декларативные макросы (и они таки синтаксические), но какой же кривой и мозгодробительный синтаксис!

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

Ну и как вы без специального синтаксиса сделаете макрос, добавляющий ну вот хотя бы возможность сериализации структуры? Вот чтобы в цикле пройтись по всем полям и сериализовать их, учитывая их тип данных?

Или вот взять макрос intrusive_adapter из крейта intrusive_collections, добавляющий новую структуру с особой небезопасной реализацией конкретного трейта. Как его делать просто на чистых функциях?

То, что вы описываете, похоже скорее на const fn, которые в Rust тоже есть.

Интересно, почему vec! не делает reserve. Размер ведь известен во время компиляции

Потому что это просто пример того, как это можно реализовать, написанный автором статьи. В самом Rust он реализован по-другому. Если в двух словах: в случае перечисления элементов, вектор создаётся из boxed slice - то есть, как раз за одну аллокацию нужного размера.

Sign up to leave a comment.