вступление Несмотря на то, что Rust предоставляет свою книгу по Rust, мне было сложно понять ключевое слово . Я спросил себя: «Я единственный, у кого такая проблема?» Быстрый поиск в Google подтвердил, что я не одинок. mut В результате я решил написать эту статью, чтобы дать подробное объяснение ключевого слова . Эта статья предназначена для тех, кто знаком с языками высокого уровня, такими как Python или JavaScript. mut Переменные Чтобы создать неизменяемую переменную в Rust, просто напишите . Это просто. Если вы хотите создать переменную, которую можно будет изменить позже, просто добавьте ключевое слово после . В Rust есть полезное соглашение, которое способствует ясности намерений. let x = 1337 mut let Добавление ключевого слова сообщает другим, что эта переменная будет изменена где-то в другом месте кода. Хорошо. mut Давайте визуализируем это. Здесь две переменные, и . let mut x = 1337 let y = 42 Ссылки На данный момент все просто. Однако при использовании ссылок все становится немного запутанным. Давайте создадим некоторые. mut let mut x = 1337; let y = 42; let x_ref = &mut x; let y_ref = &y; Я создал две отсылки (или «позаимствовал» в терминах Rust). Одна из них — изменяемая ссылка, а другая — ссылка только для чтения. Давайте создадим для этого схему еще раз. В данной схеме у меня 4 переменные, 2 из которых являются ссылками. Обе ссылочные переменные являются неизменяемыми и не имеют ключевого слова после , что означает, что я не могу изменить то, на что они указывают. Однако я все еще могу изменить значение, на которое они ссылаются. mut let *x_ref = 777; Если вы напишете это, компилятор Rust не будет жаловаться, а значение (а не сама ссылка) изменится на . Однако на схеме есть красный квадрат, указывающий, что отсутствует опция изменчивости. Итак, почему я могу изменить значение, на которое оно ссылается? x 777 x_ref Вернемся к схеме . let x_ref = &mut x Первый белый блок содержит имя: . Второй сообщает мне о типе, хранящемся в этой переменной. В полной форме, без каких-либо неявных аннотаций типов, я могу написать следующее: x_ref let x_ref: &mut i32 = &mut x; Я могу интерпретировать это так: давайте создадим с именем , которая будет содержать на , и немедленно инициализируем ее на значение в переменной . неизменяемую переменную x_ref изменяемую ссылку i32 изменяемой ссылкой i32 x Это означает, что я могу изменить значение, на которое оно указывает, но не могу изменить значение (или адрес) ссылки. Другими словами, я не могу написать что-то вроде: let x_ref: &mut i32 = &mut x; let mut z = 0; x_ref = &mut z; // Not allowed! Что касается схем, я хочу изменить направление, на которое указывает стрелка в блоке кода выше. Однако, даже если переменная является изменяемой, я не могу изменить стрелку, поскольку проблема заключается в неизменяемости самого . z x_ref Чтобы изменить направление стрелки, мне нужно изменить адрес, хранящийся в переменной . Однако я не могу этого сделать, поскольку переменная неизменяема. x_ref Давай сделаем это! let mut x: i32 = 1337; let mut x_ref: &mut i32 = &mut x; // I've added mut before x_ref let mut z = 0; x_ref = &mut z; // Allowed! Здесь, вокруг , слишком много случаев , верно? Опишем их. x_ref mut : я создаю изменяемую переменную с именем , что означает, что я могу изменить ее значение позже. let mut x_ref x_ref : Я утверждаю, что переменная будет содержать изменяемые ссылки на некоторое значение типа . &mut i32 i32 : я заимствую (получаю ссылку) переменную . &mut x x Затем я создал переменную с именем и присвоил ей значение . Позже, когда я написал , я указал, что понимаю как изменяемую переменную, которая может содержать только ссылки на значения . z 0 x_ref = &mut z x_ref i32 Поскольку тип — , я могу присвоить его адрес переменной . Чтобы получить адрес , я использовал синтаксис . z i32 x_ref z &mut z Схема. Ментальный трюк Взгляните на в операторе, это может показаться немного очевидным, но… = let mut x_ref = &mut x; … Я рассматриваю это как разделитель (особенно если повернуть его на 90 градусов), который делит утверждение на два подпредложения: левое и правое. Левая часть предоставляет информацию , а правая . о самой переменной — о значении Когда я использую оператор разыменования для изменения значения... * *x_ref = 100; ... я не меняю значение переменной . Вместо этого я меняю значение, на которое ссылается . x_ref x_ref Неизменяемые ссылки Раньше я часто использовал . Что, если я опущу некоторые из них? mut let i = 1; let j = 2; let mut k = &i; Могу ли я изменить значение здесь? Используя технику делителя, ответить довольно просто. Я могу изменить значение (я вижу слева), но значение (справа) является неизменяемой ссылкой на (здесь нет ). i k mut i mut Поэтому… let i = 1; let j = 2; let mut k = &i; k = &j; // This is legal. *k = 3; // This is not. Схема. Заключение В этой статье мы разобрали нюансы ключевого слова и ссылок. Помните, что существует различие между и содержащей ссылку. Наша хитрость? mut изменяемой ссылкой изменяемой переменной, Использование знака в качестве мысленного разделителя для лучшего понимания присваиваний в Rust. Эта простая визуализация может прояснить многие недоразумения. = Приятного кодирования!