`map` 调用在这里有任何目的吗?

huangapple go评论71阅读模式
英文:

Does the `map` call serve any purpose here?

问题

以下是翻译好的内容:

看起来从 这里 引用的代码如下:

pub fn iter(&self) -> impl Iterator<Item = (&usize, &T)> + '_ {
    self.values.iter()
}

有什么不同吗?

英文:

Code:

pub fn iter(&amp;self) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;T)&gt; + &#39;_ {
    self.values.iter().map(|(key, value)| (key, value))
}

Quoted from here, it seems following is enough:

pub fn iter(&amp;self) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;T)&gt; + &#39;_ {
    self.values.iter()
}

Any difference?

答案1

得分: 2

是的,前者返回一个类型,它实现了 Iterator&lt;Item = (&amp;usize, &amp;T)&gt; + &#39;_,而后者返回一个类型,它实现了 Iterator&lt;Item = &amp;(usize, T)&gt; + &#39;_

这里是一个最小的示例:

pub fn iter1(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
    v.iter().map(|(key, value)| (key, value))
}

pub fn iter2(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
    v.iter()
}

使用这个错误信息编译失败:

error[E0271]: expected `std::slice::Iter&lt;&#39;_, (usize, i32)&gt;` to be an iterator that yields `(&amp;usize, &amp;i32)`, but it yields `&amp;(usize, i32)`
 --&gt; src/lib.rs:5:37
  |
5 | pub fn iter2(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
  |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&amp;(usize, i32)`, found tuple
6 |     v.iter()
  |     -------- return type was inferred to be `std::slice::Iter&lt;&#39;_, (usize, i32)&gt;` here
  |
  = note: expected reference `&amp;(usize, i32)`
                 found tuple `(&amp;usize, &amp;i32)`

有关此错误的更多信息,请尝试 `rustc --explain E0271`。
error: could not compile `playground` due to previous error

Playground.

前者之所以能工作,是因为 Rust 的模式语法中内置了一种称为 绑定模式 的符号糖:

当引用值与非引用模式匹配时,它将自动被视为 ref 或 ref mut 绑定。

因此,它基本上是 v.iter().map(|&amp;(ref key, ref value)| (key, value)) 的语法糖,这使得前者为什么有效更加清晰,但后者为什么无效。

英文:

Yes, the former returns a type that implements Iterator&lt;Item = (&amp;usize, &amp;T)&gt; + &#39;_ while the latter returns a type that implements Iterator&lt;Item = &amp;(usize, T)&gt; + &#39;_.

Here a minimal example:

pub fn iter1(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
    v.iter().map(|(key, value)| (key, value))
}

pub fn iter2(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
    v.iter()
}

fails to compile with this error message:

error[E0271]: expected `std::slice::Iter&lt;&#39;_, (usize, i32)&gt;` to be an iterator that yields `(&amp;usize, &amp;i32)`, but it yields `&amp;(usize, i32)`
 --&gt; src/lib.rs:5:37
  |
5 | pub fn iter2(v: &amp;[(usize, i32)]) -&gt; impl Iterator&lt;Item = (&amp;usize, &amp;i32)&gt; + &#39;_ {
  |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&amp;(usize, i32)`, found tuple
6 |     v.iter()
  |     -------- return type was inferred to be `std::slice::Iter&lt;&#39;_, (usize, i32)&gt;` here
  |
  = note: expected reference `&amp;(usize, i32)`
                 found tuple `(&amp;usize, &amp;i32)`

For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground` due to previous error

Playground.

The former works thanks to ergonomics build into Rust's pattern syntax called binding modes:

> When a reference value is matched by a non-reference pattern, it will be automatically treated as a ref or ref mut binding.

So it is basically syntactic sugar for v.iter().map(|&amp;(ref key, ref value)| (key, value)), which makes it clearer why the former works, but the latter doesn't.

huangapple
  • 本文由 发表于 2023年2月24日 17:29:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75554803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定