Recursive function with "can't capture dynamic environment in a fn item"

Hello. I'm trying to solve this problem posted in Code Wars. My tentative solution would be:

use std::cmp::{max, min};

use tailcall::tailcall;

pub fn sq_in_rect(lng: i32, wdth: i32) -> Option<Vec<i32>> {
    let min = min(lng, wdth);
    let max = max(lng, wdth);
    let mut squares = vec![];

    #[tailcall]
    fn dec(a: i32, b: i32, mut sqs: Vec<i32>, diff: i32) -> Vec<i32> {
        sqs.push(a);
        if a == b {
            sqs
        } else {
            dec(min(a, diff), max(a, diff), sqs, b - a)
        }
    }

    Some(dec(min, max, squares, max - min))
}

but I get the following compiling error:

error[E0434]: can't capture dynamic environment in a fn item
  --> src/rectangles_into_squares.rs:16:17
   |
16 |             dec(min(a, diff), max(a, diff), sqs, b - a)
   |                 ^^^
   |
   = help: use the `|| { ... }` closure form instead

error[E0434]: can't capture dynamic environment in a fn item
  --> src/rectangles_into_squares.rs:16:31
   |
16 |             dec(min(a, diff), max(a, diff), sqs, b - a)
   |                               ^^^
   |
   = help: use the `|| { ... }` closure form instead

Any idea on how to circumvent the problem?

The problem seems to be this:

Inside the dec function, you're calling min(a, diff) and max(a, diff), likely referring to std::cmp::{min, max}. But at that point they were already shadowed by the quoted lets, so function tries to capture the numeric values and fails.

If you use other names for these two variables...

let min_val = min(lng, wdth);
let max_val = max(lng, wdth);

// skipped

Some(dec(min_val, max_val, squares, max_val - min_val))

...this should work.

4 Likes

Thank you very much. As a matter of fact that solved the problem.