我正在学习/试验Rust,在我用这种语言找到的所有优雅中,有一个让我感到困惑并且看起来完全不合适的特点.
在进行方法调用时,Rust会自动取消引用指针.我做了一些测试来确定确切的行为:
struct X { val: i32 }
impl std::ops::Deref for X {
type Target = i32;
fn deref(&self) -> &i32 { &self.val }
}
trait M { fn m(self); }
impl M for i32 { fn m(self) { println!("i32::m()"); } }
impl M for X { fn m(self) { println!("X::m()"); } }
impl M for &X { fn m(self) { println!("&X::m()"); } }
impl M for &&X { fn m(self) { println!("&&X::m()"); } }
impl M for &&&X { …Run Code Online (Sandbox Code Playgroud) 甲FnMut闭合无法克隆,出于显而易见的原因,但Fn封闭件具有一个不可变的范围; 有没有办法创建一个Fn闭包的"重复" ?
尝试克隆它会导致:
error[E0599]: no method named `clone` found for type `std::boxed::Box<std::ops::Fn(i8, i8) -> i8 + std::marker::Send + 'static>` in the current scope
--> src/main.rs:22:25
|
22 | fp: self.fp.clone(),
| ^^^^^
|
= note: self.fp is a function, perhaps you wish to call it
= note: the method `clone` exists but the following trait bounds were not satisfied:
`std::boxed::Box<std::ops::Fn(i8, i8) -> i8 + std::marker::Send> : std::clone::Clone`
Run Code Online (Sandbox Code Playgroud)
以某种方式将原始指针传递给Fn周围是安全的,例如:
let func_pnt = …Run Code Online (Sandbox Code Playgroud) 我觉得很奇怪,Iterator::take_while它取得了迭代器的所有权.这似乎是一个有用的功能,能够获取满足某些功能但仍保留原始迭代器中其余元素的前x个元素.
我知道这与懒惰的实现不兼容take_while,但仍然感觉很有用.这只是被认为不足以包含在标准库中,还是还有其他一些我没有看到的问题?
我目前正在尝试在Rust中实现一个简单的Parser-Combinator库.为此,我希望有一个泛型map函数来转换解析器的结果.
问题是我不知道如何复制持有闭包的结构.示例是Map以下示例中的结构.它有一个mapFunction存储函数的字段,它接收前一个解析器的结果并返回一个新结果.Map它本身就是一个可以与其他解析器进一步组合的解析器.
但是,对于要组合的解析器,我需要它们是可复制的(具有Clone特征限制),但是我该如何提供Map呢?
示例:(只有伪代码,很可能无法编译)
trait Parser<A> { // Cannot have the ": Clone" bound because of `Map`.
// Every parser needs to have a `run` function that takes the input as argument
// and optionally produces a result and the remaining input.
fn run(&self, input: ~str) -> Option<(A, ~str)>
}
struct Char {
chr: char
}
impl Parser<char> for Char {
// The char parser returns Some(char) if …Run Code Online (Sandbox Code Playgroud) 编者注:这个代码示例来自1.0之前的Rust版本,当时实现了许多迭代器
Copy.此代码的更新版本会产生不同的错误,但答案仍包含有价值的信息.
我正在尝试编写一个函数来将一个字符串分成几个字母和数字; 例如,"test123test"会变成[ "test", "123", "test" ].这是我到目前为止的尝试:
pub fn split(input: &str) -> Vec<String> {
let mut bits: Vec<String> = vec![];
let mut iter = input.chars().peekable();
loop {
match iter.peek() {
None => return bits,
Some(c) => if c.is_digit() {
bits.push(iter.take_while(|c| c.is_digit()).collect());
} else {
bits.push(iter.take_while(|c| !c.is_digit()).collect());
}
}
}
return bits;
}
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,永远循环.似乎它iter每次调用都使用一个克隆take_while,从同一个位置一遍又一遍地开始.我希望iter每次都使用相同的方法,在所有each_times上推进相同的迭代器.这可能吗?
我想使用Peekable作为一个新的基础cautious_take_while,其作用类似于操作 take_while距离IteratorExt,但不消耗第一个失败的项目.(还有一个问题是这是否是一个好主意,以及是否有更好的方法来实现Rust的这一目标 - 我很乐意在这个方向上提示,但主要是我试图了解我的代码在哪里断).
我试图启用的API基本上是:
let mut chars = "abcdefg.".chars().peekable();
let abc : String = chars.by_ref().cautious_take_while(|&x| x != 'd');
let defg : String = chars.by_ref().cautious_take_while(|&x| x != '.');
// yielding (abc = "abc", defg = "defg")
Run Code Online (Sandbox Code Playgroud)
我在这里创造了一个MCVE,但是我得到了:
:10:5:10:19错误:无法移出借来的内容:10 chars.by_ref().cautious_take_while(|&x | x!='.');
据我所知,TakeWhile在我的函数签名方面,我遵循与Rust自己相同的模式,但我看到了与借用检查器不同的不同行为.有人可以指出我做错了吗?
我有一个看起来像这样的结构:
pub struct MyStruct<F>
where
F: Fn(usize) -> f64,
{
field: usize,
mapper: F,
// fields omitted
}
Run Code Online (Sandbox Code Playgroud)
我如何实现Clone这个结构?
我发现复制函数体的一种方法是:
let mapper = |x| (mystruct.mapper)(x);
Run Code Online (Sandbox Code Playgroud)
但这会导致mapper与mystruct.mapper.