А все языки с ручными управлением памятью зарание и гарантированно уступают всему ранее рассмотренному.
Слишком смелое утверждение, так как цели в задаче могут быть разными - к примеру, с упором на перформанс по скорости или эффективность по памяти, а не только на простоту реализации или безопасность. Да и в последнем случае есть различия в способах избегания того же разыменовывания нулевых указателей - где-то надо руками следить за этим, как в плюсах, а где-то позаботились на уровне языка, как в том же Rust.
ручное жонглирование бесконечными borrow/drop/upgrade/clone тратит больше времени и сил, чем собственно решение задачи.
Вызовы borrow стоит спрятать в методы реализации, погрузив Rc<RefCell> в обёртку, чтобы потроха не торчали на клиенте. - Тогда и drop не понадобится. А upgrade это аналог lock в C++, так что здесь странная претензия именно к Rust, а clone - явное дешёвое копирование shared pointer-а - это как раз базовая вещь в Rust - явное клонирование в противовес неявному в плюсах.
Если, как полагается, прятать детали реализации, то можно не трогая клиент заменять реализацию на другие варианты, например, на арену с хендлами вместо указателей.
А выставить из обёртки удобно методы, либо возвращающие обёрнутые объекты с shared pointer внутри, либо принимающие коллбэк в виде замыкания для чтения либо модификации сложных объектов - например, для чтения или модификации стиля, что у вас делалось через style.clone_resized(style.size + 1.0).
Это показывает противоречие в философии языка:
безопасность без падений остается недостижимым идеалом,
В чём же противоречие? Rust не декларирует безопасность без паник, хотя и без них тоже можно. Паники обычно применяются как раз для недопущения UB либо при нарушении инвариантов.
Симпатично выглядит, привлекает простота и лаконичность. Нравится идея опускания запятых в конце строки и имена ключей без кавычек, и одновременно обязательное наличие кавычек для строчных значений - новомодное их опускание в этой части в некоторых форматах приводит к неоднозначностям и ненужному усложнению спецификации и реализации, и даже к ухудшению восприятия.
Непонятно, почему минусы - человек поделился идеей (и неплохой) и своей реализацией - только за это уже молодец, разве нет?
При этом сам lib инициируется выше по стеку перед Calc.
Всё это из-за строгой гарантии на этапе компиляции, что полученные указатели на функции не протухнут, когда библиотека выгрузится.
Альтернативой вынесению lib из Calc было бы использовать unsafe: либо для self-referential struct, либо для приведения lifetime 'a к 'static для Symbol.
Отличная статья, спасибо, всё доступно и с деталями!
Небольшая описка:
Для процедурных макросов аналога $crate нет, поэтому используйте proc-macro-crate::crate_name("your-support"), а затем подставьте либо crate::…, если вы находитесь в нём же, либо реальное имя из Cargo.toml.
Слишком смелое утверждение, так как цели в задаче могут быть разными - к примеру, с упором на перформанс по скорости или эффективность по памяти, а не только на простоту реализации или безопасность. Да и в последнем случае есть различия в способах избегания того же разыменовывания нулевых указателей - где-то надо руками следить за этим, как в плюсах, а где-то позаботились на уровне языка, как в том же Rust.
Вызовы borrow стоит спрятать в методы реализации, погрузив Rc<RefCell> в обёртку, чтобы потроха не торчали на клиенте. - Тогда и drop не понадобится. А upgrade это аналог lock в C++, так что здесь странная претензия именно к Rust, а clone - явное дешёвое копирование shared pointer-а - это как раз базовая вещь в Rust - явное клонирование в противовес неявному в плюсах.
Если, как полагается, прятать детали реализации, то можно не трогая клиент заменять реализацию на другие варианты, например, на арену с хендлами вместо указателей.
А выставить из обёртки удобно методы, либо возвращающие обёрнутые объекты с shared pointer внутри, либо принимающие коллбэк в виде замыкания для чтения либо модификации сложных объектов - например, для чтения или модификации стиля, что у вас делалось через style.clone_resized(style.size + 1.0).
В чём же противоречие? Rust не декларирует безопасность без паник, хотя и без них тоже можно. Паники обычно применяются как раз для недопущения UB либо при нарушении инвариантов.
Симпатично выглядит, привлекает простота и лаконичность. Нравится идея опускания запятых в конце строки и имена ключей без кавычек, и одновременно обязательное наличие кавычек для строчных значений - новомодное их опускание в этой части в некоторых форматах приводит к неоднозначностям и ненужному усложнению спецификации и реализации, и даже к ухудшению восприятия.
Непонятно, почему минусы - человек поделился идеей (и неплохой) и своей реализацией - только за это уже молодец, разве нет?
Так не скомпилируется в Rust:
Здесь libloading::Symbol должен иметь lifetime в списке параметров дженерика, то есть рабочим был бы вариант:
Здесь 'a это lifetime от lib, который в этом случае передаётся в load:
При этом сам lib инициируется выше по стеку перед Calc.
Всё это из-за строгой гарантии на этапе компиляции, что полученные указатели на функции не протухнут, когда библиотека выгрузится.
Альтернативой вынесению lib из Calc было бы использовать unsafe: либо для self-referential struct, либо для приведения lifetime 'a к 'static для Symbol.
Как говорится, добро пожаловать в Rust :)
Отличная статья, спасибо, всё доступно и с деталями!
Небольшая описка:
Верно было бы так (если минимально править):
А вообще понятнее было бы использовать переименованное название зависимости как например renamed-support.