Самый общий ответ на ваш вопрос заключается в том, что вы не можете / не можете. Блокировка стандартного ввода возвращает тип, который ссылается на значение Stdin
. Вы не можете создать локальное значение (stdin()
), взять ссылку на него (.lock()
) и затем вернуть эту ссылку.
Если вы просто хотите сделать это внутри функции , не возвращая ее , тогда вы можете создать объект признака:
use std::io::{self, prelude::*, BufReader};
fn example(file: Option<std::fs::File>) {
let stdin;
let mut stdin_lines;
let mut file_lines;
let input: &mut Iterator<Item = _> = match file {
None => {
stdin = io::stdin();
stdin_lines = stdin.lock().lines();
&mut stdin_lines
}
Some(file) => {
file_lines = BufReader::new(file).lines();
&mut file_lines
}
};
for line in input {
// ...
}
}
Или создайте новую универсальную функцию, в которую вы можете передать конкретный итератор любого типа:
use std::io::{self, prelude::*, BufReader};
fn example(file: Option<std::fs::File>) {
match file {
None => finally(io::stdin().lock().lines()),
Some(file) => finally(BufReader::new(file).lines()),
}
}
fn finally(input: impl Iterator<Item = io::Result<String>>) {
for line in input {
// ...
}
}
Вы можете поместить в структуру объект признака или универсальный тип, даже если вы не можете его вернуть:
struct A<'a> {
input: &mut Iterator<Item = io::Result<String>>,
}
struct A<I>
where
I: Iterator<Item = io::Result<String>>,
{
input: I,
}
Если вы чувствуете себя предприимчивым, вы можете использовать небезопасный код / ящики, упаковывающие небезопасный код, для хранения значения Stdin
и итератора, ссылающегося на него вместе, что не является универсально безопасным.
Смотри также:
input: Box<Lines<BufRead>>,
Это недопустимо, потому что Lines
не является признаком. Вы хотите либо:
use std::io::{prelude::*, Lines};
pub struct A {
pub input: Lines<Box<BufRead>>,
}
Или
use std::io;
pub struct A {
pub input: Box<Iterator<Item = io::Result<String>>>,
}