使用以下链接列表定义:
enum List<T> {
Nil,
Cons(T, ~List<T>)
}
我正在尝试编写一个map函数(即将操作应用于列表的每个元素并返回一个新列表) . 我正在尝试使用教程中提供的指南和其他不同的地方(例如Rust for Rubyists),因此我尝试使用值并借用指针而不是拥有指针 . 这引出了以下函数定义:
fn map<T1, T2>(f: |T1| -> T2, xs: &List<T1>) -> ~List<T2> { ... }
我认为这是有道理的;变换器函数对值起作用,list参数是借用的指针 . 我返回一个拥有的指针,因为我需要使用递归调用的返回值来构造一个值 .
现在,让我们来看看身体:
fn map<T1, T2>(f: |T1| -> T2, xs: &List<T1>) -> ~List<T2> {
match xs {
&Nil => ~Nil,
&Cons(x, ~ref rest) => ~Cons(f(x), map(f, rest))
}
}
这是我的第一次尝试; ~ref
语法有点不直观,但我在教程中找到了它 . 此实现不编译 .
demo.rs:25:15: 25:16 error: cannot bind by-move and by-ref in the same pattern
demo.rs:25 &Cons(x, ~ref rest) => ~Cons(f(x), map(f, rest))
^
demo.rs:25:19: 25:27 note: by-ref binding occurs here
demo.rs:25 &Cons(x, ~ref rest) => ~Cons(f(x), map(f, rest))
^~~~~~~~
error: aborting due to previous error
好吧,显然在进行模式匹配时,内部模式必须具有相同的移动语义,没有混合和匹配 . 让我们尝试在 x
模式之前添加 ref
:
fn map<T1, T2>(f: |T1| -> T2, xs: &List<T1>) -> ~List<T2> {
match xs {
&Nil => ~Nil,
&Cons(ref x, ~ref rest) => ~Cons(f(x), map(f, rest))
}
}
demo.rs:25:44: 25:45 error: mismatched types: expected `T1` but found `&T1` (expected type parameter but found &-ptr)
demo.rs:25 &Cons(ref x, ~ref rest) => ~Cons(f(x), map(f, rest))
^
error: aborting due to previous error
再次出错;模式匹配是可以的,但是我没有正确的类型来调用我的闭包 . 使用语法 f(*x)
是非法的,所以我需要更改我的闭包类型以接受借用的指针:
fn map<T1, T2>(f: |&T1| -> T2, xs: &List<T1>) -> ~List<T2> {
match xs {
&Nil => ~Nil,
&Cons(ref x, ~ref rest) => ~Cons(f(x), map(f, rest))
}
}
最后这个版本有效 .
任何人都可以告诉我,这是什么 Map 应该在Rust看起来像?
1 回答
这是一张可以接受的 Map ,但我有一些评论 .
首先,只需从
map()
的类型签名中知道f
需要&T1
而不是T1
. 这是因为取T1
意味着它必须将值移动到闭包中,但它在借用的List<T1>
上运行,因此无法移动它 .其次,你的 Map 不需要返回
~List<T2>
,它只能返回List<T2>
,你可以自己将递归调用包装在~
指针中 . 这看起来像第三,实现这一目标的最好方法是不要写
map()
,而是编写iter()
,它产生一个实现Iterator<&T1>
的类型 . 迭代器隐式支持map . 然后,您还需要实现FromIterator
,以允许您将映射的结果转换回List
.这是迭代器和示例用法的实现: