简而言之,我想找到一种创建数组的语法
静态生命周期(或至少与样本一样长的生命周期
向量的一个),并返回它的切片。
你会想要这样的东西:
fn sliced(array: [Token; 3]) -> &'static [Token] { unimplemented!() }
所以你可以在你的例子中这样使用它:
let samples: Vec<(&str, &[Token])> = vec![
("a string", sliced([Token::PLUS, Token::MINUS, Token::PLUS])),
// ...
但它有两个问题。第一个也是最明显的一点是,您无法从不接受 static 引用的函数中获取 static 引用(在这种情况下,它只会返回它)。
因此,由于您希望切片至少与您的数组一样长,您要么声明一个 const/static 切片(这还需要一个 const/static 声明其数组),或者您首先使用let 语句声明数组,然后制作切片。 (这是我在下面的第一个替代方案中所做的。)如果您在使用vec! 及其切片中创建数组,则数组以vec! 结束其生命,使切片无效。作为一个例子,考虑这个,由于同样的原因而失败:
fn main() {
let slice;
{
let array: [u8; 3] = [1,2,3];
slice = &array;
}
}
sliced 函数的第二个问题是它的输入数组有一个固定的大小,并且您希望对任意大小的数组进行通用处理。但是,Rust[1] 目前不支持此功能。您必须使用切片才能处理任意大小的数组。
那么,一种可能性是执行以下操作 [playpen]:
enum Token {
PLUS,
MINUS,
MUL,
}
fn validate(samples: &[(&str, &[Token])]) {
unimplemented!()
}
fn main() {
let tokens_0 = [Token::PLUS, Token::MINUS, Token::PLUS];
let tokens_1 = [Token::MUL];
let samples: Vec<(&str, &[Token])> = vec![
("a string", &tokens_0),
("another string", &tokens_1),
];
validate(&samples);
}
这里有两个关于您的代码的更改。
第一,此代码通过引用将数组 ([T; N]) 隐式强制转换为切片 (&[T])。这是samples 声明为Vec<(&str, &[Token])> 类型所要求的。稍后,当使用 vec! 时,通过传递对数组的引用,从而引发适当的强制转换,这一点得到了满足。
第二,它在使用 vec! 宏之前创建了 Token 的数组,这保证了它们可以在它创建的 Vec 中被引用,在 vec! 之后保持这些引用有效完毕。在解决之前的类型不匹配之后,这是必要的。
附录:
或者,为方便起见,您可能更喜欢使用Vec 而不是切片。考虑以下替代方案 [playpen]:
enum Token {
PLUS,
MINUS,
MUL,
}
fn validate<T>(samples: &[(&str, T)]) where
T: AsRef<[Token]>
{
let _: &[Token] = samples[0].1.as_ref();
unimplemented!()
}
fn main() {
let samples: Vec<(&str, Vec<Token>)> = vec![
("a string", vec![Token::PLUS, Token::MINUS, Token::PLUS]),
("another string", vec![Token::MUL]),
];
validate(&samples);
}
在这种情况下,绑定在元组的第二个元素上的AsRef<[Token]> 接受您可以从中获取&[Token] 的任何类型,提供一个返回预期引用的as_ref() 方法。 Vec<Token> 就是这种类型的一个例子。
[1] “Rust 目前不支持超过数组类型大小的泛型。” [source]