【发布时间】:2023-01-08 06:19:04
【问题描述】:
我正在研究(又一个)Advent of Code 框架。因为谜题的解决方案应该保持简单易写,目标是让下面的代码工作未修改的:
/// Sometimes a string is easier to work with.
fn run1(_input: &str) {
}
/// Sometimes bytes are easier or faster.
fn run2(_input: &[u8]) {
}
fn main() {
run1(&input());
run2(&input());
}
在这里,input 函数从文件加载输入。因此,它必须返回一个拥有的类型,而不是一个引用。这可以是 Vec<u8> 或 String。
为此,我编写了以下 Input 特征:
/// Type of puzzle input that can be loaded: string or raw bytes.
trait Input {
fn from_bytes(bytes: Vec<u8>) -> Self;
}
impl Input for String {
fn from_bytes(bytes: Vec<u8>) -> Self {
String::from_utf8(bytes).unwrap()
}
}
impl Input for Vec<u8> {
fn from_bytes(bytes: Vec<u8>) -> Self {
bytes
}
}
现在如何定义 input() 函数?天真的签名:
/// Imagine this loads some input from a file.
fn input<I: Input>() -> I {
I::from_bytes(vec![])
}
这很好,直到我尝试调用它。 run1 采用&str,但&input() 最多只能是&String 类型,导致如下错误:
error[E0277]: the trait bound `str: Input` is not satisfied
--> src/main.rs:10:11
|
10 | run1(&input());
| ^^^^^ the trait `Input` is not implemented for `str`
|
= help: the trait `Input` is implemented for `String`
note: required by a bound in `input`
--> src/main.rs:32:13
|
32 | fn input<I: Input>() -> I {
| ^^^^^ required by this bound in `input`
str不能作为input()的返回类型,因为它不是Sized,所以impl Input for str是不可能的。因此,从String 到str 的强制转换必须发生在input() 函数之外。
我想表达的是,可以将返回类型从String强制转换为str,但是当类型推断发现需要str时,仍然可以推断出I = String。我认为 Deref 特性在这里发挥作用,但我一直无法弄清楚如何用它解决问题。
这可以工作吗,还是我对类型系统的要求太多了?
【问题讨论】:
-
为什么不指定类型参数,即
run1(&input::<String>()); run2(&input::<Vec<u8>>());?或者拥有String和Vec<u8>? -
为什么不指定类型参数:因为这需要快速编写,没有人有时间这样做。为什么不采用拥有的价值:因为它不是惯用的 Rust。
-
我认为您不应该关心 AOC 代码中的惯用 Rust,即用即弃。
-
@ChayimFriedman 出于同样的原因,人们并不都参与 AoC。请允许我自己决定我做什么和不关心什么。
-
如果你对内存泄漏没问题,你可以让它像这样工作:playground
标签: rust