我正在通过实现我的一个小F#片段来试验Rust.
我正处于想要构造一串字符的地步.这是F#:
let rec internalCheck acc = function
| w :: tail when Char.IsWhiteSpace(w) ->
internalCheck acc tail
| other
| matches
| here
..这可以称得上是这样的:internalCheck [] "String here"
当::
运营商表示右手边是"列表中的其余部分."
所以我检查了Rust文档,并且有像这样的解构向量的示例:
let v = vec![1,2,3]; match v { [] => ... [first, second, ..rest] => ... }
..等等.然而,现在这是slice_patterns
功能门的背后.我尝试过类似的东西:
match input.chars() { [w, ..] => ... }
这告诉我功能门需要使用非稳定版本.
所以我下载multirust
并安装了最新的夜间我可以找到(2016-01-05
),当我最终使slice_patterns
功能工作时...我遇到了无法解决的语法错误和"休息"(在上面的例子中)不被允许.
那么,是否有一种等效的方法来构造一串字符,利用::
类似于Rust的功能...... 基本上我想将1个角色与守卫相匹配,并在随后的表达式中使用"其他所有内容".
如果答案是"不,没有",这是完全可以接受的.我当然无法在任何地方在线找到这种类型的许多示例,并且切片模式匹配在功能列表上似乎并不高.
(如果在Rust文档中遗漏了一些内容,我将很乐意删除此问题)
您可以使用与byte
切片匹配的模式:
#![feature(slice_patterns)] fn internal_check(acc: &[u8]) -> bool { match acc { &[b'-', ref tail..] => internal_check(tail), &[ch, ref tail..] if (ch as char).is_whitespace() => internal_check(tail), &[] => true, _ => false, } } fn main() { for s in ["foo", "bar", " ", " - "].iter() { println!("text '{}', checks? {}", s, internal_check(s.as_bytes())); } }
您可以将它与char
切片一起使用(其中char
是Unicode标量值):
#![feature(slice_patterns)] fn internal_check(acc: &[char]) -> bool { match acc { &['-', ref tail..] => internal_check(tail), &[ch, ref tail..] if ch.is_whitespace() => internal_check(tail), &[] => true, _ => false, } } fn main() { for s in ["foo", "bar", " ", " - "].iter() { println!("text '{}', checks? {}", s, internal_check(&s.chars().collect::>())); } }
但截至目前,它不适用于&str
(生产E0308).我认为这是最好的&str
,既不是在这里,也不是在那里,它是一个byte
片层,但Rust试图保证它是一个有效的UTF-8并试图提醒你使用&str
unicode序列和字符而不是字节.所以为了有效地匹配&str
我们必须明确地使用这个as_bytes
方法,基本上告诉Rust"我们知道我们在做什么".
无论如何,这是我的阅读.如果您想深入挖掘Rust编译器的源代码,可以从问题1844开始,浏览那里链接的提交和问题.
基本上我想将1个角色与守卫相匹配,并在随后的表达式中使用"其他所有内容".
如果您只想匹配单个字符,那么使用字符迭代器获取字符并匹配字符本身可能比将整个UTF-8 &str
转换为&[char]
切片更好.例如,使用chars迭代器,您不必为characters数组分配内存.
fn internal_check(acc: &str) -> bool { for ch in acc.chars() { match ch { '-' => (), ch if ch.is_whitespace() => (), _ => return false, } } return true; } fn main() { for s in ["foo", "bar", " ", " - "].iter() { println!("text '{}', checks? {}", s, internal_check(s)); } }
您还可以使用chars迭代器来拆分&str
Unicode标量值边界:
fn internal_check(acc: &str) -> bool { let mut chars = acc.chars(); match chars.next() { Some('-') => internal_check(chars.as_str()), Some(ch) if ch.is_whitespace() => internal_check(chars.as_str()), None => true, _ => false, } } fn main() { for s in ["foo", "bar", " ", " - "].iter() { println!("text '{}', checks? {}", s, internal_check(s)); } }
但请记住,截至目前,Rust无法保证将此尾递归函数优化为循环.(尾部调用优化将成为该语言的一个受欢迎的补充,但由于与LLVM相关的困难,它迄今尚未实现).