LINUX.ORG.RU

Не пойму замыкания

 


1

3

Объясните, пожалуйста, логику

fn main() {
    use std::mem;

    let mut d = "FOO".to_owned();
    let mut n = 0;

    let f = || {
        n += 1;
        d.push_str("BAR");
        mem::drop(d);
    };

    f();
}

Но если удалить переменную d, то будет ошибка «cannot borrow `f` as mutable, as it is not declared as mutable». Почему так?

fn main() {
    let mut n = 0;

    let f = || {
        n += 1;
    };

    f();
}
Deleted

mem::drop превращает твою лямбду в FnOnce, так что вызов f() её поглощает, и не надо объявлять ее mut

fn main() {
    use std::mem;

    let mut d = "FOO".to_owned();
    let mut n = 0;

    let f = || {
        n += 1;
        d.push_str("BAR");
        mem::drop(d);
    };

    f();
    f();
}
----
error[E0382]: use of moved value: `f`
  --> src/main.rs:14:5
   |
13 |     f();
   |     - value moved here
14 |     f();
   |     ^ value used here after move
MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от MyTrooName

Это я понимаю. Не понимаю, почему в первом случае срабатывает просто let f = || ...

Deleted
()
fn main() {
    let mut n = 0;

    let mut f = || {
        n += 1;
    };

    f();
    f();
    println!("{}", n);
}
----
2
MyTrooName ★★★★★
()
Ответ на: комментарий от Deleted

Вообще неочевидное поведение

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

ну вообще да, не слишком очевидно, но вполне корректно

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от MyTrooName

Просто зачем делали mut и move, если в ряде случаев их можно не писать

А вообще, спасибо за ответ 👍

Deleted
()
Ответ на: комментарий от Deleted

Просто зачем делали mut и move, если в ряде случаев их можно не писать

move в ряде случаев можно не писать, т.к. иногда компилятор сам в состоянии понять, что тут move.

с mut несколько другое: вызов FnMut можно делать только если сама лямбда мутабельна, т.к. переменная с лямбдой остается в зоне видимости и доступна дальше, а внутреннее состояние лямбды (в данном случае переменная n) меняется

с FnOnce это не требуется, т.к. переменная с лямбдой все равно больше недоступна

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

с FnOnce это не требуется, т.к. переменная с лямбдой все равно больше недоступна

Аа. Точняк

Deleted
()
Ответ на: комментарий от Deleted

Просто зачем делали mut и move, если в ряде случаев их можно не писать

А вообще, спасибо за ответ 👍

Ты руками дропаешь биндинг, и чему-то удивляешься. move, кстати, наоборот пишется в ряде случаев, а обычно не пишется.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Deleted

Они же рожают новые кресты, ты хотел чтобы все очевидно было? Пока язык с замашками раста не придет писать бывший делфист, в лоулевеле будет вечный implicity hell.

anonymous
()
Ответ на: комментарий от anonymous

Пока язык с замашками раста не придет писать бывший делфист

Значит вся надежда на майкрософт)

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.