2016-09-15 18 views
0

引数に基づいていくつかのポートを作成していますが、ポートは次の関数に渡すのに十分長くは存続しません。より良いことに、これを静的にディスパッチするために適応させる方法は?Rustで入力ソースを切り替える最も良い方法

fn init<'a>(matches: getopts::Matches) { 
    let in_port: &mut Read = match matches.opt_str("i") { 
     Some(filename) => &mut File::open(filename).expect("Couldn't open input file.") as &mut Read, 
     _ => &mut io::stdin() as &mut Read, 
    }; 
    let out_port: &mut Write = match matches.opt_str("o") { 
     Some(filename) => &mut File::create(filename).expect("Couln't open output file") as &mut Write, 
     _ => &mut io::stdout() as &mut Write, 
    }; 
    run(in_port, out_port); 
} 
+1

が意図A' ' '雑多ですか? –

答えて

1

あなたはすべての試合アームに直接run関数を呼び出すことで、静的なディスパッチを使用することができます。

use std::fs::File; 
use std::io::{Read, Write}; 

fn init(i: Option<&str>, o: Option<&str>) { 
    match i { 
     Some(filename) => init2(File::open(filename).expect("Couldn't open input file."), o), 
     None => init2(std::io::stdin(), o), 
    } 
} 

fn init2<R: Read>(i: R, o: Option<&str>) { 
    match o { 
     Some(filename) => run(i, File::create(filename).expect("Couldn't open output file")), 
     None => run(i, std::io::stdout()), 
    } 
} 

fn run<R: Read, W: Write>(i: R, o: W) { 
    unimplemented!() 
} 
+0

美しく働いて、静的なディスパッチを使用するためのボーナスポイント。ありがとうございました! –

1

が最も簡単な解決策は、ヒープでそれらを入れて、Boxあなたのオブジェクトになります。

それはそれらを返す意味ので、私は個人的に、initrunを分離することを好む:

fn init(matches: Matches) -> (Box<Read>, Box<Write>) { 
    let in_port: Box<Read> = match matches.opt_str("i") { 
     Some(filename) => Box::new(File::open(filename).expect("Couldn't open input file.")), 
     _ => Box::new(stdin()), 
    }; 
    let out_port: Box<Write> = match matches.opt_str("o") { 
     Some(filename) => Box::new(File::create(filename).expect("Couln't open output file")), 
     _ => Box::new(stdout()), 
    }; 
    (in_port, out_port) 
} 
1

問題は、あなたが破壊しようとしている何かへの参照を返すようにしようとしているということです。

let in_port: &mut Read = match matches.opt_str("i") { 
    Some(filename) => &mut File::open(filename).expect("Couldn't open input file.") as &mut Read, 
    _ => &mut io::stdin() as &mut Read, 
}; 

ブロック内では、作成されたFileは、それが入っている式の長さだけ続く一時的なものです。具体的な型を隠すことができるように、値ではなく参照を使用していると仮定します。 d特性オブジェクト。 1つの方法は、オブジェクトを所有するBox<Trait>ということです。

fn init<'a>(i: Option<&str>, o: Option<&str>) { 
    let mut in_port: Box<Read> = match i { 
     Some(filename) => Box::new(File::open(filename).expect("Couldn't open input file.")), 
     _ => Box::new(io::stdin()), 
    }; 
    let mut out_port: Box<Write> = match o { 
     Some(filename) => Box::new(File::create(filename).expect("Couln't open output file")), 
     _ => Box::new(io::stdout()), 
    }; 
    run(&mut in_port, &mut out_port); 
} 

playground

関連する問題