ПрограммированиеBackend разработчик

Объясните особенности работы с неизменяемыми и изменяемыми переменными в Rust. Почему в отличие от других языков переменные по умолчанию неизменяемы?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

История вопроса

Во многих популярных языках программирования, таких как C или JavaScript, переменные по умолчанию изменяемы. В Rust сами авторы языка сделали важный выбор в пользу неизменяемости переменных по умолчанию: такое решение связано с безопасностью кода и уменьшением количества ошибок, связанных с неожиданными изменениями состояния переменных.

Проблема

Главная проблема изменяемых переменных — сложность отладки и поиска ошибок, связанных с неявными изменениями значений. Особенно сложно понимать поведение кода, когда переменные меняются в разных частях программы, а контроль их изменений теряется. Это может привести к багам и неожиданным результатам, особенно при написании многопоточных приложений либо при сложных взаимозависимостях в коде.

Решение

В Rust переменные по умолчанию неизменяемы с помощью ключевого слова let. Чтобы сделать переменную изменяемой, нужно явно указать mut. Это повышает надёжность кода, делает неизменяемость осознанным выбором и уменьшает вероятность случайных изменений.

Пример кода:

let x = 5; // неизменяемая переменная let mut y = 10; // изменяемая переменная y += 1; // корректно x += 1; // ошибка компиляции!

Ключевые особенности:

  • Неизменяемость по умолчанию — для безопасности.
  • Явное указание изменяемости через mut.
  • Компилятор предотвращает модификации неизменяемых переменных на этапе компиляции.

Вопросы с подвохом.

Можно ли изменить поле структуры, если сама переменная структуры объявлена как неизменяемая?

Нет, если переменная структуры объявлена как неизменяемая, то её поля тоже неизменяемы. Чтобы изменять поля, нужно объявлять переменную с mut.

Пример кода:

struct Point { x: i32, y: i32 } let mut p = Point { x: 0, y: 0 }; p.x = 5; // ok let p2 = Point { x: 1, y: 2 }; p2.x = 3; // ошибка компиляции!

Если переменная mut, можно ли ссылаться на неё одновременно несколькими изменяемыми ссылками?

Нет, в Rust одновременно существует только одна изменяемая ссылка на объект. Это правило предотвращает состояние гонки данных.

Можно ли объявить массив из неизменяемых объектов как изменяемый и изменять его содержимое?

Да. Если переменная массива объявлена как mut, его элементы можно менять, но если содержимое типа массива не поддерживает изменяемость, то элементы не изменяемы.

Типовые ошибки и анти-паттерны

  • Использование mut без необходимости, что делает код менее безопасным.
  • Попытка изменять содержимое переменной без объявления mut.
  • Недоразумения с изменяемостью вложенных структур.

Пример из жизни

Негативный кейс

В проекте переменные объявляют изменяемыми по привычке, даже когда в этом нет нужды. Из-за этого одна из переменных случайно изменяется в середине программы другим методом, что вызывает сложноуловимую ошибку на продакшне.

Плюсы:

  • Быстрота написания кода без необходимости следить за мутируемостью.

Минусы:

  • Сложность отладки и высокий риск багов, связанных с лишними изменениями.

Позитивный кейс

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

Плюсы:

  • Легче читать и поддерживать код, меньше скрытых изменений.
  • Компилятор сам ловит ошибки связанных с изменяемостью.

Минусы:

  • Иногда приходится писать чуть больше кода или проходить небольшую кривую обучения для новичков, не привыкших к такому стилю.