What is the difference between a filter (| x |) and a filter (| & x |)?

The Rust Book has an example of calling filter() on an iterator:

 for i in (1..100).filter(|&x| x % 2 == 0) { println!("{}", i); } 

Below is an explanation, but I had trouble understanding it:

This will print all even numbers from one to one hundred. (Note that since the filter does not consume duplicate elements, it passes a reference to each element, and therefore the filter predicate uses the & x pattern to extract the whole.)

This, however, does not work:

 for i in (1..100).filter(|&x| *x % 2 == 0) { println!("i={}", i); } 

Why the closing argument closes the link |&x| instead of |x| ? And what's the difference between using |&x| and |x| ?

I understand that using the |&x| more efficiently, but I'm puzzled by the fact that I didn't have to play the pointer x using *x .

+6
source share
1 answer

When used as a pattern match (and the closing arguments and functions also match the pattern), & binds to the link, making the variable dereferenced .

 fn main() { let an_int: u8 = 42; // Note that the `&` is on the right side of the `:` let ref_to_int: &u8 = &an_int; // Note that the `&` is on the left side of the `:` let &another_int = ref_to_int; let () = another_int; } 

Is there an error:

 error: mismatched types: expected `u8`, found `()` 

If you look at your error message for your case, it means that you cannot dereference it, because it is not a link:

 error: type `_` cannot be dereferenced 

I did not need to dereference the x pointer using * x.

This is because you implicitly dereferenced it to match the pattern.

I understand that using the link | & x | more effective

If this were true, then there would be no reason to use anything other than links! Namely, links require additional indirection in order to get to real data. There is some measurable clipping point, where the transfer of elements by value is more efficient than the transfer of links to them.

If so, why use |x| does not give an error? From my experience with C, I would expect to get a pointer here.

And you do it as a link. x is a reference to (in this example) a i32 . However, the % operator is specified by the Rem flag, which is implemented for all reference / value pairs:

 impl Rem<i32> for i32 impl<'a> Rem<i32> for &'a i32 impl<'a> Rem<&'a i32> for i32 impl<'a, 'b> Rem<&'a i32> for &'b i32 

This does not allow you to explicitly dereference it.

Or does Rust implicitly allocate a copy of the original x value on the stack here?

It resolutely does not . In fact, it would be unsafe to do this unless the iterated elements are implemented by Copy (or potentially Clone , in which case it can also be expensive). This is why links are used as an argument to closure.

+8
source

Source: https://habr.com/ru/post/988802/


All Articles