Rust 弦锈中F#的Cons图案的等效物
我正在通过实现我的一个小F#片段来试验生锈 我正处于要对字符串进行解构的位置。这是F#:Rust 弦锈中F#的Cons图案的等效物,rust,tail,Rust,Tail,我正在通过实现我的一个小F#片段来试验生锈 我正处于要对字符串进行解构的位置。这是F#: 让rec内部检查acc=功能 |w::当Char.IsWhiteSpace(w)-> 内部检查acc尾部 |其他 |火柴 |这里 …可以这样调用:internalCheck[]“String here”其中:运算符表示右侧是“列表的其余部分” 因此,我查看了Rust文档,并提供了如下分解向量的示例: let v = vec![1,2,3]; match v { [] => ...
让rec内部检查acc=功能
|w::当Char.IsWhiteSpace(w)->
内部检查acc尾部
|其他
|火柴
|这里
…可以这样调用:internalCheck[]“String here”
其中:
运算符表示右侧是“列表的其余部分”
因此,我查看了Rust文档,并提供了如下分解向量的示例:
let v = vec![1,2,3];
match v {
[] => ...
[first, second, ..rest] => ...
}
……等等。然而,现在这是在切片模式
特征门之后。我试过类似的方法:
match input.chars() {
[w, ..] => ...
}
这告诉我特性门需要非稳定版本才能使用
因此,我下载了multirust
,并安装了我能找到的最新版本(2016-01-05
),当我最终获得slice\u patterns
功能时。。。关于语法和“rest”(在上面的例子中)不被允许,我遇到了无数的错误
那么,有没有一种等效的方法可以利用类似于:
的功能来解构字符串。。。锈迹斑斑?基本上,我想将一个字符与一个守卫匹配,并在下面的表达式中使用“其他所有内容”
如果答案是“不,没有”,这是完全可以接受的。当然,我在任何地方都找不到这种类型的例子,切片模式匹配在功能列表中似乎也不高
(如果我在Rust文档中遗漏了什么,我会很高兴地删除这个问题)我不这么认为。切片模式也不太可能适应这种情况,因为模式的“和其余”部分位于数组模式内部,这意味着某种方式可以将所述模式放入字符串中,这意味着一种不存在的转义机制
此外,Rust没有合适的“连接”操作符,并且它所拥有的操作符不能参与解构。所以,我不会为这件事屏住呼吸。就在这里发布这件事。。。它似乎做了我想做的事。作为一个简单的测试,这将只打印字符串中的每个字符,但在找到空白字符时打印
找到空白字符
。它以递归方式执行此操作,并对字节向量进行解构。我必须向@ArtemGr大喊一声,他给了我灵感,让我研究如何使用字节,看看这是否解决了我在char
s中遇到的编译器问题
毫无疑问,在这里我还没有意识到内存问题(复制/分配等;尤其是字符串
实例)。。。但我会在深入研究锈迹的内部机理的同时,对其进行研究。它也可能比它需要的要详细得多。。这正是我修修补补后的结果
#![feature(slice_patterns)]
use std::iter::FromIterator;
use std::vec::Vec;
fn main() {
process("Hello world!".to_string());
}
fn process(input: String) {
match input.as_bytes() {
&[c, ref _rest..] if (c as char).is_whitespace() => { println!("Found a whitespace character"); process(string_from_rest(_rest)) },
&[c, ref _rest..] => { println!("{}", c as char); process(string_from_rest(_rest)) },
_ => ()
}
}
fn string_from_rest(rest: &[u8]) -> String {
String::from_utf8(Vec::from_iter(rest.iter().cloned())).unwrap()
}
输出:
H
e
l
l
o
Found a whitespace character
w
o
r
l
d
!
显然,由于它是针对单个字节进行测试的(并且在重建字符串时只考虑可能的UTF-8字符),因此它不适用于宽字符。我的实际用例只需要ASCII空间中的字符。。所以现在这已经足够了
我想,要处理更宽的字符,锈迹模式匹配需要能够键入强制(我不相信您目前可以这么做?),因为
Chars可以将模式匹配与字节
切片一起使用:
#![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标量值):
您还可以使用迭代器在Unicode标量值边界上拆分&str
:
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相关的困难,到目前为止尚未实现)。似乎对我有用:。也许语法已经改变了?仍然值得一个完整的答案。@ArtemGr是的,对不起,这似乎有效。然而,我似乎无法让它在字符串上工作。这就是问题的重点(如果不清楚的话,我应该重新措辞吗?)。顺便说一句@ArtemGr,谢谢你提供的操场链接-我不知道Rust有这样的操场(拇指支撑)。怎么样?游乐场似乎有一个暂时的问题,但在我的工作站上,它打印“匹配…1匹配…2”;看得很公平。这是我在F#中喜欢的一个特性,所以我确实希望它在Rust中是可能的。尽管如此,这并不能阻止我调查锈病。。。所以谢谢你:)+1去那里。除非您只使用ASCII,否则我认为您需要使用&[char]
切片,唯一的瓶颈是从&str
高效地获取它。我本来会使用堆栈分配的数组()的,但这是另一回事。这太棒了!我真的很感激你花了这么多时间来整理这件事。你的样本中有100件东西(包括工作和非工作)我可以从中学习。你有贡献。。我将来肯定能胜任这项任务。。一旦我对生锈感到更舒服了。再次感谢!我真的很感激!不客气!)另外,我已经在本地检查了这个答案中的所有样本,所有样本都应该有效。如果其中一些不适合您,请告诉我。由于LLVM相关的困难,也因为TCO使堆栈跟踪看起来不一样。IIRC,关键字been
保留用于选择未来的TCO。我意识到我从未接受过你的回答@ArtemGr。对此表示歉意。@SimonWhitehead NP!)
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));
}
}
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));
}
}