2014-08-27 1 views
1

Я играю с новыми закрытиями в Rust, и я столкнулся с ситуацией, которая снова показала мне, что я еще не полностью понял правила владения.Правила владения ржавчинами в контексте закрытий

#![feature(unboxed_closures)] 
#![feature(overloaded_calls)] 

fn main() { 
    let mut test = 5i; 
    let do_something = ref |:| { println!("{}", test) }; 
    test = 6i; 
    do_something(); 

    println!("{}", test); 
} 

Этот код не говорил мне, что назначение test = 6i; является недействительным, поскольку test уже заимствованы к do_something закрытия.

Но читать правила владения (из Руководства Rust), кажется, действует мне:

1.You управления, когда этот ресурс освобождаться.

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

3. Вы можете предоставить этот ресурс, возможно, одному заемщику. НО

4. Когда вы это сделаете, вы также не можете одолжить его иначе, изменчиво или неизменно.

5.Вы не можете с легкостью одолжить его, если вы в настоящее время предоставляете его кому-то.

В чем проблема с кодом выше. test является владельцем и do_something должен иметь только непреложный ссылка. Не следует ли изменять значение test, если единственная ссылка на него, которую мы предоставляем кому-то, была неизменяемая?

РАЗВЕЙТЕ

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

#![feature(unboxed_closures)] 
#![feature(overloaded_calls)] 

use std::cell::Cell; 

fn main() { 
    let test = Cell::new(5i); 
    let do_something = ref |:| { println!("{}", test) }; 
    test.set(6i); 
    do_something(); 

    println!("{}", test); 
} 

Но интересно, почему это печатает

5 
6 

и не

6 
6 

Как бы мне нужно изменить код, чтобы напечатать это?

6 
6 
+0

Почему вы писали '|: |' вместо '||'? Я не знаю точно, почему, но, похоже, это имеет значение, в котором вы ищете. – Levans

+0

А вы пишете. '||' по-прежнему являются старыми закрытиями, поскольку '|: |' является одним из новых, и я думал, что 'ref |: |' должен быть новым типом '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' Мне, наверное, нужно копать глубже :) – Christoph

ответ

2

Как вы процитировали себя:

Вы не можете одолжить его mutably, если вы в настоящее время кредитование его кому-то.

Как вы уже кредитование test к do_something, вы не можете получить доступ к нему, прежде чем mutably do_something выходит из области видимости.

+0

Ну, но я не хочу одолжить * изменчиво *. То, как я это понимаю, «тест» - это владелец (не кредитование), и это только * lend * out * immutable * to' do_something'. – Christoph

+0

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

+0

@ Christoph no. Вы можете одолжить один раз ** или ** неизменно много раз, но не одновременно в одно и то же время. И владелец, обращающийся к данным, считается кредитом. – Levans

2

Ответ на ваше наблюдение:

Это, кажется, происходит потому, что Cell является Copy, поэтому он копируется в крышку.Если вы сделаете это (теперь ref до закрытия не имеет значения и может быть опущено):

#![feature(unboxed_closures)] 
#![feature(overloaded_calls)] 

use std::cell::Cell; 

fn main() { 
    let test = Cell::new(5i); 
    let test_ref = &test; 
    let do_something = |:| { println!("{}", test_ref.get()) }; 
    test.set(6i); 
    do_something(); 

    println!("{}", test.get()); 
} 

Затем он печатает две 6 с.

Однако, я думаю, что это поведение несколько неожиданно. Я, конечно, ожидал бы, что закрытие с префиксом ref займет все их окружение по ссылке. Я только что представил для этого issue.

+0

Спасибо! Я также думал, что 'ref |: |' был таким же, как старый '||'. Заинтересованы в том, чтобы увидеть отзыв о выпуске, который вы создали. – Christoph

+0

@ Кристоф, насколько я помню, синтаксис '|: |' для закрытий FnOnce; это 'ref | & mut: |' закрытие - это то, что должно быть таким же, как и старое '' '' '' '' '' '' '' '' '' '' '. Опять же, насколько я помню, идея заключалась в том, чтобы отказаться от старых закрытий и использовать их синтаксис как сокращенное выражение для '| & mut :: |'. –

+0

Ну ладно, но даже это печатает '5, 6' – Christoph