【发布时间】:2014-04-04 17:04:41
【问题描述】:
使用如下链表定义:
enum List<T> {
Nil,
Cons(T, ~List<T>)
}
我正在尝试编写一个映射函数(即对列表的每个元素应用一个操作并返回一个新列表)。我正在尝试使用本教程和其他不同地方(例如Rust for Rubyists)中给出的指南,因此我尝试尽可能使用值和借用指针而不是拥有的指针。这导致我得到以下函数定义:
fn map<T1, T2>(f: |T1| -> T2, xs: &List<T1>) -> ~List<T2> { ... }
我认为这是有道理的;转换器函数对值起作用,列表参数是借来的指针。我返回一个拥有的指针,因为我需要将一个值与递归调用的返回值相结合。
现在,让我们看看身体:
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))
}
}
这个版本终于可以工作了。
谁能告诉我地图在 Rust 中是否应该是这样的?
【问题讨论】: