我可以在函数链接时遇到 None 时立即 return 吗?

Can I return immediately when meets None while function chaining?

Problem.
我对此很好奇,因为如果可以的话,我认为我不需要这段代码中的东西。
我特别想要 .filter_map(|ch| ch.to_digit(10)).
ch.to_digit() returns None 如果 ch 不是数字。那么我想要 return false.
如果我能做到这一点,我想我不需要 if !code.chars().all(|ch| ch.is_digit(10) || ch.is_whitespace()) 这张支票。 (我只是想知道如果在链接中进行检查,我可以这样做吗?)

如果不允许,有没有办法在函数链中进行异常检查?
谢谢。

/// Check a Luhn checksum.
pub fn is_valid(code: &str) -> bool {
    if code.trim().len() <= 1 {
        return false;
    }
    if !code.chars().all(|ch| ch.is_digit(10) || ch.is_whitespace()) {
        return false;
    }

    code.chars()
        .rev()
        .filter_map(|ch| ch.to_digit(10))
        .enumerate()
        .map(|( i, n)|
            match i % 2 {
                0 => n,
                _ if n == 9 => n,
                _ => (n * 2) % 9,
            }
        )
        .sum::<u32>() % 10 == 0
}

Can I return immediately when meets None while function chaining?

不是真的。您可以 mapOption(而不是 filter_map),然后 collect Iterator<Option<_>>Option<Vec<_>>:

let items = vec![0_u16, 1, 2];

let res: Option<Vec<u16>> = items
    .iter()
    .map(|x| x.checked_add(1))
    .collect();

assert_eq!(res, Some(vec![1, 2, 3]));

let res: Option<Vec<u16>> = items
    .iter()
    .map(|x| x.checked_sub(1))
    .collect();

assert_eq!(res, None);

如果最后有一个None,那么你就可以保释了。

但老实说,我只是使用沼泽标准 for 循环,例如:

let mut sum = 0;
for (i, n) = code.chars().rev().map(|ch| ch.to_digit(10)).enumerate() {
    sum += match (i % 2, n) {
        (_, None) => return false;
        (0, Some(n)) => n,
        (_, Some(9)) => 9,
        (_, Some(n)) => (n * 2) % 9,
    }
}
sum % 10 == 0

If it's not allowed, is there some way to do exception check in function chain?

不太清楚你的意思。

你可以 try_fold:

pub fn is_valid(code: &str) -> bool {
    code.chars()
        .rev()
        .try_fold((0, 0), |acc, ch|
            // `acc.0` enumerates the valid digits
            // `acc.1` accumulates the sum
            if ch.is_whitespace() {
                Some (acc)
            } else {
                ch.to_digit (10).map (|n|
                    match acc.0 % 2 {
                        0 => (acc.0+1, acc.1 + n),
                        _ if n == 9 => (acc.0+1, acc.1 + n),
                        _ => (acc.0+1, acc.1 + (n*2)%9),
                    })
            })
        .map (|acc| acc.1 % 10 == 0)
        .unwrap_or (false)
}

Playground

但是为了可读性,我会使用@Masklinn 的直截了当的 for 循环。