2014-09-25 3 views
0

Я довольно новыми для Руст, так что я наткнулся на этот кусок кода в официальном Guideпеременные с тем же именем внутри некоторых (T) в Русте

let input = io::stdin().read_line() 
         .ok() 
         .expect("Failed to read line"); 
let input_num: Option<uint> = from_str(input.as_slice()); 

let num = match input_num { 
    Some(num) => num, 
    None  => { 
     println!("Please input a number!"); 
     return; 
    } 
}; 

Хотя понять первые два заявления (на input и inputnum), я не совсем уверен в заявлении о матче. Поэтому я проверил documentation, который показывает, что Option<T> может принимать два значения: None или Some(T) для некоторых (объект?) T. Поэтому я тестировал следующий код:

io::println( 
    match input_num { 
     Some(num) => "somenum", 
     None  => { 
      println!("Please input a number only!"); 
      return; 
     } 
    } 
); 

Этот код работает должным образом; он печатает somenum, если вы вводите номер, и в противном случае он печатает сообщение об ошибке. Однако компилятор дает предупреждение: warning: unused variable: num , #[warn(unused_variable)] on by default. Это подтвердило мои подозрения, что num внутри `match используется как переменная.

Вопрос: Как это возможно, что rust не жалуется (в примере на Гида в) имеющие две переменные с тем же именем num? Или он «сдает» указатель на внутреннюю сторону num снаружи num? Также в случае пустого return что именно возвращается? Я предполагаю, что это блок (), потому что он упоминается here что

функции без -> ... неявно имеют тип возвращаемого значения ()

Edit: Извините за отсутствие очевидной точки. return непосредственно выходит из функции, не утруждая себя чем-либо помещением в num.

P.S. Я заметил, что использование cargo build для компиляции не дает предупреждений во второй раз (не внося никаких изменений). Делает ли cargo отслеживание версий или что-то еще?

ответ

1

Есть ли у вас опыт работы с Java или C#? Многие основные языки программирования позволяют вам использовать shadow переменную с другой переменной с таким же именем в области нового блока. Например, посмотрите на этот C# код:

using System; 

public class Test 
{ 
    public static void Main() 
    { 
     int x = 10; 
     { 
      int x = 20; 
      Console.WriteLine(x); 
     } 
     Console.WriteLine(x); 
    } 
} 

На самом деле Ржавчина является более гибким с точки зрения затенения: вы можете теневые переменные столько раз, сколько вы хотите без явного создавая брекет-блок.

fn main() { 
    let i = 10i32; 
    let i = "foo"; 
    println!("{}", i); 
} 

Здесь первая i и второй i не имеют отношения. Мы просто теряем способ использовать (см.) Первый i.

Это подтвердило мои подозрения, что число внутри `match используется как переменная.

Да, сопоставление образцов может вводить новые переменные. Но новая переменная num, введенная путем сопоставления шаблонов, не имеет прямого отношения к внешнему num, значение которого задается выражением match.

Я могу перевести код ржавчины на менее идиоматической Руст, чтобы проиллюстрировать, что происходит:

let num = 
    if input_num.is_some() { 
     let num = input_num.unwrap(); 
     num 
    } else { 
     println!("Please input a number!"); 
     return; 
    } 
; 

Что касается не соблюдая предупреждения от cargo build, я подозреваю, что это было потому, что Cargo уже построила .o из вашего кода и Бесполезная Не пытайтесь повторить одну и ту же работу дважды, зная, что в вашем коде не было изменений.

+0

За 9 месяцев программирования Java я не обнаружил ни одного примера затенения. Возможно, потому что это немного запутанно. Спасибо за ссылки и дополнительную информацию. – theindigamer

+0

Хм, я обнаружил, что Java действительно намного менее разрешительна с затенением http://doanduyhai.wordpress.com/2012/07/07/variable-shadowing/ http://stackoverflow.com/questions/4623334/question-about-variable -scope-and-shadowing-in-java http://stackoverflow.com/questions/141140/why-does-java-not-have-block-scoped-variable-declarations Неудивительно, что у вас не было шансов встретиться Это. – nodakai

+0

В Rust у вас есть образец соответствия и доктрина все-есть-выражение. Они подталкивают вас к примерам затенения имени. Java тоже нет, поэтому неудивительно, что вы не получаете столько затенения. –

Смежные вопросы