gpt4 book ai didi

rust - 返回并使用匹配的通用类型

转载 作者:行者123 更新时间:2023-11-29 07:53:20 25 4
gpt4 key购买 nike

我正在开发一个简单的 Rust 应用程序,它接受 stdin 并在其基础上运行。我想让每个命令返回一个结果向量。

不同的命令可能会返回不同类型的向量; list 方法返回一个由 PathBuf 组成的向量,但默认匹配臂返回字符串:

use std::{io, fs};
use std::path::PathBuf;

fn main() {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed to read line");
let chars_to_trim: &[char] = &['\n'];
let trimmed_input: &str = input.trim_matches(chars_to_trim);

let no_match = vec!["No Match"];

let result = match trimmed_input {
"list" => list(),
_ => no_match,
};
}

fn list() -> Vec<PathBuf> {
println!("{}", "list of lockfiles here");
let entries = fs::read_dir("/tmp").expect("Failed to read /tmp");
let all: Result<_, _> = entries.map(|entry| entry.map(|e| e.path())).collect();
all.expect("Unable to read an entry")
}

这会导致编译失败:

error[E0308]: match arms have incompatible types
--> src/main.rs:12:22
|
12 | let result = match trimmed_input {
| ^ expected struct `std::path::PathBuf`, found &str
|
= note: expected type `std::vec::Vec<std::path::PathBuf>`
= note: found type `std::vec::Vec<&str>`
note: match arm with an incompatible type
--> src/main.rs:14:18
|
14 | _ => no_match,
| ^^^^^^^^

处理这个问题的惯用 Rust 方法是什么?我已通读有关泛型的文档,但不确定如何应用它。

最佳答案

这是一个简化的测试用例:

use std::path::PathBuf;

fn main() {
let paths: Vec<PathBuf> = Vec::new();
let defaults: Vec<&'static str> = Vec::new();

let result = match 1 {
1 => paths,
_ => defaults,
};
}

正如错误消息试图说明的那样,Rust 要求单个变量始终具有相同的类型。让一个变量成为一组中的未知类型根本没有意义。

您可以做的最直接的事情是创建一个 enum 来包装您拥有的两种情况:

use std::path::PathBuf;

enum MyThing<'a> {
Str(&'a str),
Path(PathBuf),
}

fn main() {
let paths: Vec<PathBuf> = Vec::new();
let defaults: Vec<&'static str> = Vec::new();

let result: Vec<_> = match 1 {
1 => paths.into_iter().map(MyThing::Path).collect(),
_ => defaults.into_iter().map(MyThing::Str).collect(),
};
}

您也可以选择一个中间地带并转换为该类型,也许是 String:

use std::path::PathBuf;

fn main() {
let paths: Vec<PathBuf> = Vec::new();
let defaults: Vec<&'static str> = Vec::new();

let result: Vec<_> = match 1 {
1 => paths.into_iter().map(|p| p.to_string_lossy().into_owned()).collect(),
_ => defaults.into_iter().map(|s| s.to_string()).collect(),
};
}

第三种选择是创建一个trait 并为两种类型实现它。然后您可以创建一个特征对象。此选项最接近您可能熟悉的动态语言。它增加了一个额外的间接层,允许更大的灵 active :

use std::path::PathBuf;

trait MyTrait {
fn size(&self) -> u8;
}

impl MyTrait for PathBuf {
fn size(&self) -> u8 {
15
}
}

impl<'a> MyTrait for &'a str {
fn size(&self) -> u8 {
88
}
}

fn main() {
let paths: Vec<PathBuf> = Vec::new();
let defaults: Vec<&'static str> = Vec::new();

let result: Vec<_> = match 1 {
1 => paths.into_iter().map(|p| Box::new(p) as Box<MyTrait>).collect(),
_ => defaults.into_iter().map(|s| Box::new(s) as Box<MyTrait>).collect(),
};
}

关于rust - 返回并使用匹配的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28589764/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com