How do I do this functionally?

Is there any way to use this algorithm but have it written in a functional style?

fn main() {
    let mut n = 5;
    let mut count = 0;
    while n != 0 {
        n &= n - 1;
        count += 1;
    }
    assert_eq!(count, 5_i32.count_ones());
}

You can use try_fold() for while-like functionality: Playground

use core::ops::ControlFlow::{Break, Continue};

fn main() {
    let n = 5_i32;
    let count = core::iter::repeat(())
        .try_fold((0, n), |(count, n), _| {
            if n > 0 {
                Continue((count + 1, n & (n - 1)))
            } else {
                Break(count)
            }
        });

    assert_eq!(count, Break(n.count_ones()));
}
3 Likes

Personally, I'd do it this way: (Playground)

use std::iter::successors;

fn main() {
    let n = 5_i32;
    let count = successors(Some(n), |n| Some(n & (n - 1)))
        .take_while(|&n| n > 0)
        .count();
    assert_eq!(Ok(count), n.count_ones().try_into());
}
5 Likes

Thanks! That's exactly what I was looking for.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.