1

I was reading the chapter on higher order functions of Rust by Example. Where they present the following canonical example:

fn is_odd(n: u32) -> bool {
    n % 2 == 1
}

fn main() {
   let upper = 1000;

   println!("imperative style: {}", acc);

   let sum_of_squared_odd_numbers: u32 =
       (0..).map(|n| n * n)                             // All natural numbers squared
            .take_while(|&n_squared| n_squared < upper) // Below upper limit
            .filter(|&n_squared| is_odd(n_squared))     // That are odd
            .fold(0, |acc, n_squared| acc + n_squared); // Sum them
}

Simple enough. But I realized that I don't understand the type of parameter n_squared. Both take_while and filter accept a function that takes a parameter by reference. That makes sense to me, you want to borrow instead of consuming the values in the map.

However, if n_squared is a reference, why don't I have to dereference it before comparing its value to limit or equally surprising; why can I pass it directly to is_odd() without dereferencing?

I.e. why isn't it?

   |&n_squared| *n_squared < upper

When I try that the compiler gives the following error:

error[E0614]: type `{integer}` cannot be dereferenced
  --> src\higherorder.rs:13:34
   |
13 |         .take_while(|&n_squared| *n_squared <= upper)
   |      

Indicating that n_squared is an i32 and not &i32. Looks like some sort pattern matching/destructuring is happening here, but I was unable to find the relevant documentation.

4
  • If you write |n_squared|, you'll get the expected error and using *n_squared in the body will fix it. See reddit.com/r/rust/comments/16b9wh/… Commented Mar 8, 2019 at 9:45
  • 1
    Since I edited the comment and you might not have seen it: I've added a link to an old Reddit discussion of exactly this issue reddit.com/r/rust/comments/16b9wh/…. While Rust has changed a lot, this seems to still be what's going happening. Commented Mar 8, 2019 at 9:53
  • 2
    The documentation is in doc.rust-lang.org/1.30.0/book/2018-edition/….` Commented Mar 8, 2019 at 11:35
  • @AlexeyRomanov Perfect! That's what I was looking for. Commented Mar 8, 2019 at 11:48

1 Answer 1

6

You are using function parameter destructuring:

|&n_squared| n_squared < upper

is functionally equivalent to:

|n_squared| *n_squared < upper

To understand this better, imagine you're passing a tuple of type &(i32, i32) to a lambda:

|&(x, y) : &(i32, i32)| x + y
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.