Привет.

Статья не предполагает, что вы узнаете что-то новое из Rust, или вы научитесь ему. Это скорее эксперимент показать ребенку как он выглядит изнутри (Rust, не ребенок), а не как на нем надо писать.

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

Тут я постарался посмотреть на ситуацию с точки зрения "книжки с картинками", как язык живет, а не как мы привыкли.

Дисклеймер — в статье речь не про Copy-тип, к которым относятся, например,  i32, f64, bool, char, &T. А про move-типы (например, String), которые перемещают значения.

Ну, попробуем.

Отталкиваемся от того, что в Rust значением (ячейкой памяти) может владеть только одна переменная. Введем обозначения: let — "позволим", = — "владеть", и еще mut — кеш, наличка (деньги).

let

Позволим a владеть House:

let a = String::from("House");

Позволим b владеть этим House. По всем правилам, предыдущий владелец уходит из дома.

let b = a;

Теперь:

println!("a = {}", a);

Будет ошибочка, a теперь не имеет прав что-либо делать со значением (своим House), так он его отдал.

mut

Но и это еще не все, владеть это лишь как арендовать чужой House. Вы не можете его изменять.

Тут снова будет ошибка:

b.push_str(" with Pool");

Если вы хотите его менять, вы должны купить House, за валюту mut:

let mut c = b;
c.push_str(" with pool");
println!("{}", c);//House with pool

&

Мы можем разделить владение House, например, пустив жить приятеля. Ты передаешь приятелю связку ключей (&):

let d = &c;
println!("{}", c);
println!("{}", d);

Но есть нюанс. По правилам приличия, если пустили гостей, нельзя делать ремонт. Следующий код даст ошибку:

let d = &c;
c.push_str(" with sandbox");// если пустили гостей, нельзя делать ремонт
println!("{}", c);
println!("{}", d);// вот гость

Можно дождаться пока гости уйдут:

let d = &c;
println!("{}", d);// тут гость вышел
c.push_str(" with sandbox");

Непонятно? В самом конце статьи есть пояснение про гостей.

& mut

Но тут приятель захотел еще джакузи. Так как это вносит изменение в House, ты просишь оплатить часть House и тогда он может менять твой House тоже. Ты передаешь ему ключи в обмен на деньги (&mut).

  let e = &mut c;
  e.push_str(" and with hot tub");
  println!("{}", e);

Не забывайте, что правило действует то же — при гостях ты уже не можешь делать ремонт. Более того! Пока твой приятель сидит в джакузи, ты не можешь даже зайти в дом:

let e = &mut c;
e.push_str(" and with hot tub");
println!("{}", c);
println!("{}", e);// приятель в джакузи 

Надо дождаться, пока он выйдет:

let e = &mut c;
e.push_str(" and with hot tub");
println!("{}", e);// приятель вышел
println!("{}", c);

Это именно когда мы дали аренду за деньги &mut, а не пустили пожить бесплатно (&).

mut &mut

Сдаем в аренду другому приятелю House с правом изменения. Но приятель обладает еще своим кешем (деньгами) mut:

let mut f = &mut c;
f.push_str(" and with garden");

Дела идут в гору, мы покупаем Apartment:

let mut c2 = String::from("Apartment");

Приятель не отстает — дай, говорит, еще и Apartment погонять, кеш у меня есть (let mut f). Он съезжает с House, заезжает в Apartment, меняет и ее:

f = &mut c2;
f.push_str(" with elevator");

Принцип тот же — ключи на деньги — &mut. А инициализация let mut f нам позволяет не привязываться к одному месту (менять его). Другими словами, это про разное.

Когда приятель ушел, мы имеем по факту и измененный House и Apartment:

println!("c: {}", c);
println!("c2: {}", c2);
//c: House with pool and with sandbox and with hot tub and with garden
//c2: Apartment with elevator

Заметьте, под "приятель ушел" я имею в виду буквально "ушел", его нет, все. Rust следит за этим, и, если далее по коду переменная не применяется, он разрешает продолжить работу с вашей собственностью. Поэтому в примерах выше было ломающее мозг поведение — пока гость дома, нельзя что-то делать, но нет явных признаков, что он ушел. Переменная не применяется далее по коду — Rust считает ее "ушедшей", как-будто применили к ней delete.

Функции

За редкими исключениями, принцип тот же, не буду здесь ими грузить. Может быть в другой раз :)

Комментарии (9)


  1. panter_dsd
    12.06.2025 04:55

    Интересный подход к объяснению. Жду статьи, где будет так же рассказано про поведение гостей и хозяев в move/async мире :)


    1. anton_dolganin Автор
      12.06.2025 04:55

      Спасибо за проявленный интерес!


  1. pnmv
    12.06.2025 04:55

    мне кажется, попытка экстраполяции "повседневного опыта", в данном случае, выглядит как непреднамеренное переусложнение и запутывание.

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

    (mut - больше похоже не на валюту, а на доверенность)


    1. anton_dolganin Автор
      12.06.2025 04:55

      Да, Rust по сути и добавляет там дворника. Может быть это действительно улучшило бы понимание, спасибо ;)
      (сначала прочитал "съехавший" в контексте "сумасшедший" :D)


      1. pnmv
        12.06.2025 04:55

        (сначала прочитал "съехавший" в контексте "сумасшедший" :D)

        тоже непхохо.


  1. SemenMartynov
    12.06.2025 04:55

    Понравилась аналогия с ключами (&), даже визуально в этом что-то есть.

    Но вот с деньгами -- как то не очень...

    let mut c = b;

    Тут возникает странный момент: b не мог сам ничего изменить в доме, но смог его продать... Да ещё и с бОльшими правами, чем обладал сам. А ещё по итогу сделки деньги исчезают вместе с b...


    1. anton_dolganin Автор
      12.06.2025 04:55

      Согласен, притянуто :) , но в свое время я намучился с пониманием этой магии. Тут снова к Расту вернулся, решил освежить в памяти, и понял, что спотыкаюсь. Решил разложить по полочкам для себя. А потом подумал, что может кому еще полезно будет.

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


      1. SemenMartynov
        12.06.2025 04:55

        Помню, маленькие комнаты на одного были на вес золота.

        Просто они на стеке были))) А более крупные Box-ы нужно в куче выделять...


  1. PraetorPavel
    12.06.2025 04:55

    Мне кажется, что объяснения в таком духе (аналогии) типа &mut &[T] могут оказаться сложнее чем сама суть ;)