如何理解闭包参数
How to understand closure parameters
我是 Rust 的初学者。我试着写了一个链表来练习。
一些结构代码:
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
列表的查看功能:
错误代码:
pub fn peek(&self) -> Option<&T> {
self.head.map(|ref node| {
&node.elem
})
}
Rust 编译器 return:cannot return value referencing function parameter
。
下面的代码就可以了:
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|node| {
&node.elem
})
}
所以我猜,
错误代码实际上是以下代码的缩写:
self.head.map(|node| {
let ref ref_node = node;
&ref_node.elem
})
我的猜测是否正确?
更多,Rust中有没有类似的缩写?或者缩写规则。
错误“无法 return 值引用函数参数”在这里有点转移注意力;它与根本问题无关,只是恰好列在第一位。如果编译代码
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
pub fn peek(&self) -> Option<&T> {
self.head.map(|ref node| &node.elem)
}
}
然后你会得到两个错误,第二个错误是这段代码不起作用的原因,你需要 .as_ref()
:
error[E0507]: cannot move out of `self.head` which is behind a shared reference
--> src/lib.rs:14:9
|
14 | self.head.map(|ref node| &node.elem)
| ^^^^^^^^^ move occurs because `self.head` has type `Option<Box<Node<T>>>`, which does not implement the `Copy` trait
|
help: consider borrowing the `Option`'s content
|
14 | self.head.as_ref().map(|ref node| &node.elem)
| +++++++++
这个错误是根本原因; Option::map
消耗它的输入 Option
,这不是我们想要在这里做的。 Option::as_ref
通过采用 &Option<T>
(此处,通过隐式 auto-reference 将 self.head
转换为 &self.head
)和 return 新创建的 Option<&T>
,然后可以由 Option::map
.
消耗
但是,我知道您想知道错误代码是如何产生“cannot return...”错误的。方法如下:
- 我们知道
self.head
是一个 Option<Box<Node<T>>>
。
- 对该类型调用
Option::map()
意味着它需要一个函数 FnOnce(Box<Node<T>>) -> &T
.
- 也就是说,闭包充当一个函数,它被赋予
Box<Node<T>>
所有权。因此,在闭包中,node
是一个拥有 Box
. 的局部变量
- 闭包的主体然后尝试 return 对该框内
Node
的字段的引用,这是一个错误 E0515,因为该框由局部变量所有并且是将在函数结束时被删除。
你的 ref
修饰符没有改变,因为一个值是否被移入函数是由函数的参数类型决定的,而不是由函数体使用的 pattern/binding 类型决定的。
The error code is actually an abbreviation of the following code:
self.head.map(|node| {
let ref ref_node = node;
&ref_node.elem
})
Is my guess correct?
是也不是。您可以那样扩展代码。但这不是“真正的”代码;对于函数参数,更复杂的模式总是有效之前引入单独的普通变量 node
。无论如何,这不是编译器所做的事情;它添加了简单的代码,就像乘以 1 不会改变数字一样。但是,您 可以 在不更改程序的情况下执行此操作的事实是,无论函数本身在其参数模式中写入什么,函数参数都会被移入。
但是,不可能通过将 Rust 函数参数更改为以这种方式工作来使您的原始代码工作。导致问题的函数是 Option::map()
应用于借用的结构字段;无论传递给 map()
的函数做什么,它总是会失败,因为 Option::map()
总是消耗给它的 Option
。
我是 Rust 的初学者。我试着写了一个链表来练习。
一些结构代码:
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
列表的查看功能:
错误代码:
pub fn peek(&self) -> Option<&T> {
self.head.map(|ref node| {
&node.elem
})
}
Rust 编译器 return:cannot return value referencing function parameter
。
下面的代码就可以了:
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|node| {
&node.elem
})
}
所以我猜,
错误代码实际上是以下代码的缩写:
self.head.map(|node| {
let ref ref_node = node;
&ref_node.elem
})
我的猜测是否正确?
更多,Rust中有没有类似的缩写?或者缩写规则。
错误“无法 return 值引用函数参数”在这里有点转移注意力;它与根本问题无关,只是恰好列在第一位。如果编译代码
type Link<T> = Option<Box<Node<T>>>;
pub struct List<T> {
head: Link<T>,
}
struct Node<T> {
elem: T,
next: Link<T>,
}
impl<T> List<T> {
pub fn peek(&self) -> Option<&T> {
self.head.map(|ref node| &node.elem)
}
}
然后你会得到两个错误,第二个错误是这段代码不起作用的原因,你需要 .as_ref()
:
error[E0507]: cannot move out of `self.head` which is behind a shared reference
--> src/lib.rs:14:9
|
14 | self.head.map(|ref node| &node.elem)
| ^^^^^^^^^ move occurs because `self.head` has type `Option<Box<Node<T>>>`, which does not implement the `Copy` trait
|
help: consider borrowing the `Option`'s content
|
14 | self.head.as_ref().map(|ref node| &node.elem)
| +++++++++
这个错误是根本原因; Option::map
消耗它的输入 Option
,这不是我们想要在这里做的。 Option::as_ref
通过采用 &Option<T>
(此处,通过隐式 auto-reference 将 self.head
转换为 &self.head
)和 return 新创建的 Option<&T>
,然后可以由 Option::map
.
但是,我知道您想知道错误代码是如何产生“cannot return...”错误的。方法如下:
- 我们知道
self.head
是一个Option<Box<Node<T>>>
。 - 对该类型调用
Option::map()
意味着它需要一个函数FnOnce(Box<Node<T>>) -> &T
. - 也就是说,闭包充当一个函数,它被赋予
Box<Node<T>>
所有权。因此,在闭包中,node
是一个拥有Box
. 的局部变量
- 闭包的主体然后尝试 return 对该框内
Node
的字段的引用,这是一个错误 E0515,因为该框由局部变量所有并且是将在函数结束时被删除。
你的 ref
修饰符没有改变,因为一个值是否被移入函数是由函数的参数类型决定的,而不是由函数体使用的 pattern/binding 类型决定的。
The error code is actually an abbreviation of the following code:
self.head.map(|node| { let ref ref_node = node; &ref_node.elem })
Is my guess correct?
是也不是。您可以那样扩展代码。但这不是“真正的”代码;对于函数参数,更复杂的模式总是有效之前引入单独的普通变量 node
。无论如何,这不是编译器所做的事情;它添加了简单的代码,就像乘以 1 不会改变数字一样。但是,您 可以 在不更改程序的情况下执行此操作的事实是,无论函数本身在其参数模式中写入什么,函数参数都会被移入。
但是,不可能通过将 Rust 函数参数更改为以这种方式工作来使您的原始代码工作。导致问题的函数是 Option::map()
应用于借用的结构字段;无论传递给 map()
的函数做什么,它总是会失败,因为 Option::map()
总是消耗给它的 Option
。