Является ли использование функции для управления Cell<T> запахом кода в Rust?

Я потратил некоторое время на разработку нового проекта на Rust.

У меня возникла проблема с пониманием того, правильно ли я использую Cell. Это моя текущая проблема, в общем.

Мне нужен доступ к структуре World, которая владеет некоторыми ресурсами. В частности мне нужны (mut) ссылки на ресурсы. Проблема возникает, когда мне нужен изменяемый доступ к ресурсу (требующий &mut World) и немутируемая ссылка (требующая &World). Я не могу собрать такие ссылки вместе, так как это нарушит правила ссылок Rust.

Я хотел бы решить эту проблему с помощью Cell. У меня есть этот код в моем проекте:

    fn take_world(&self, func: impl FnOnce(World) -> World) {
        let state = self.state_ref();
        let world = state.world
            .take();

        let world = func(world);
        state.world
            .replace(world);
    }

Это должно позволить мне взять мир из ячейки, сделать то, что мне нужно, с помощью FnOnce и автоматически заменить его.

Как вы думаете, это хороший подход? Можно ли это считать запахом кода?

Другие решения могут включать рефакторинг кода, но часть World/Resource взята из библиотеки, поэтому я ничего не могу с этим поделать.

Cell для этого не нужен — достаточно изменяемой ссылки.
Chayim Friedman 17.08.2024 19:31

Кроме того, «запах кода» субъективен. Если не хотите, чтобы ваш вопрос закрыли, поставьте объективную меру.

Chayim Friedman 17.08.2024 19:31

изменяемой ссылки недостаточно, поскольку для получения двух разных ресурсов потребуются две изменяемые ссылки на мир; это или я упускаю что-то очевидное.

Nicola Picarella 17.08.2024 20:44

Вы можете взять значение с изменяемой ссылкой, а затем взять общую ссылку (только если изменяемая ссылка стоит первой).

Chayim Friedman 17.08.2024 21:15

как я могу это сделать, если им обоим одновременно требуются изменяемая и неизменяемая ссылка на мир?

Nicola Picarella 18.08.2024 12:27

Они не могут быть действительно одновременно, одно должно быть раньше другого.

Chayim Friedman 18.08.2024 12:43

вот почему я подумал об использовании сотового телефона

Nicola Picarella 18.08.2024 14:27
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
7
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это не запах кода сам по себе.

Cell предназначен для обеспечения внутренней изменчивости без затрат памяти, но он делает это, запрещая ссылочный доступ к своему содержимому, и его нельзя использовать в нескольких потоках. Таким образом, эффективно вы можете получить и установить значение в Cell, только передав право собственности (или Copy-ing). Так что это не только не запах кода, но и практически единственный способ обновить значение в Cell на основе его предыдущего значения. Обертывание его в функцию — это просто естественное расширение. Существует даже метод .update(), который скоро будет стабилизирован, который примерно делает это за вас (хотя он полагается на Copy вместо заполнения Default).

Будет ли использование Cell для манипулирования вашим World запахом кода или нет, будет зависеть от остальной части вашего дизайна и отклонится от мнения. Вы отметили Bevy, который предоставляет множество способов работы с сущностями и компонентами, поэтому я чувствую, что, вероятно, есть способ сделать то, что вы хотите, без внутренней изменчивости, но это всего лишь предположения.

Другие вопросы по теме