2016-04-16 2 views
0

私はRustでGitコマンドを作成しようとしています。私はclap引数パーザcrateを使ってコマンドラインの処理を行っています。私は自分のコマンドにオプションの引数を取って、作業するディレクトリを指定します。コマンドがオプションを受け取らない場合、ユーザーのホームディレクトリが仮定されます。matchステートメントからの値の割り当て

std::env::home_dir関数を使用してユーザーのホームディレクトリを取得できることがわかっていますが、混乱する部分は、match演算子を使用してパスの値を取得する方法です。私はpath.to_str()が十分に長く住んでいないと言って、これをコンパイルしようとするとエラーメッセージが出

use std::env; 

fn main() { 
    // Do some argument parsing stuff... 

    let some_dir = if matches.is_present("some_dir") { 
     matches.value_of("some_dir").unwrap() 
    } else { 
     match env::home_dir() { 
      Some(path) => path.to_str(), 
      None  => panic!("Uh, oh!"), 
     } 
    }; 

    // Do more things 

を:ここで私がしようとしてきたものです。 to_strから返された値がmatchスコープの長さだけ存続しますが、別の関数を呼び出す必要があるmatchステートメントからどのように値を返すことができますか?

答えて

2

path.to_str()matchアーム内にある間だけpathとして生きるpathに含ま内側列に&str参照を返します。 to_ownedを使用して、その&strの所有コピーを取得できます。あなたの場合の両方のブランチで同じ型を持つようにそれに応じてclapから値を適応させる必要があります。

let some_dir = if matches.is_present("some_dir") { 
    matches.value_of("some_dir").unwrap().to_owned() 
} else { 
    match env::home_dir() { 
     Some(path) => path.to_str().unwrap().to_owned(), 
     None  => panic!("Uh, oh!"), 
    } 
}; 

また、あなたが最初の分岐でのコピーを避けるためにCowを使用することができます。

use std::borrow::Cow; 

let some_dir: Cow<str> = if matches.is_present("some_dir") { 
    matches.value_of("some_dir").unwrap().into() 
} else { 
    match env::home_dir() { 
     Some(path) => path.to_str().unwrap().to_owned().into(), 
     None  => panic!("Uh, oh!"), 
    } 
}; 
1

何が起きているのかは、一致ステートメントのスコープが、env::home_dir()から返されたPathBufオブジェクトの所有権を取ります。そのオブジェクトへの参照を返しますが、そのオブジェクトはすぐに存在しなくなります。

解決策は、参照ではなくPathBufを返すことです(または、それをStringに変換して返します。いずれにしても、データを所有する型でなければなりません)。 matches.value_of("some_dir").unwrap()が返す値を両方のブランチが同じ型を返すように変更する必要があります。

1

ちょっと単純なトリックがあります:pathのスコープを増やして(その寿命を延ばす)、その中に参照を入れることができます。

use std::env; 

fn main() { 
    // Do some argument parsing stuff... 

    let path; // <-- 

    let some_dir = if matches.is_present("some_dir") { 
     matches.value_of("some_dir").unwrap() 
    } else { 
     match env::home_dir() { 
      Some(p) => { path = p; path.to_str().unwrap() }, 
      None  => panic!("Uh, oh!"), 
     } 
    }; 

    // Do more things 
} 

それは必要なときにpathがしか使用されているように、効率的であり、そしてプログラムで種類を変更する必要はありません。

注:.to_str()Optionを返すので、私は.to_str().unwrap()を追加しました。 Option<&str>を返す理由は、すべてのパスが有効なUTF-8シーケンスではないことに注意してください。あなたはPath/PathBufにこだわりたいと思うかもしれません。

+0

私はあなたがアドバイスした通りにパスを修正できるように、実際には文字列をPathBufオブジェクトに変換してしまいました。 –

関連する問題