Rust 函数从嵌套迭代器中返回

rust function return from within a nested iterator

提问人:Pioneer_11 提问时间:11/5/2023 更新时间:11/10/2023 访问量:60

问:

我有一个函数,可以从 9 x 9 的数字网格创建数独网格。如果发现一个无效的数字,它应该返回有关该数字所在位置的信息(其功能在注释掉的代码中)。代码当前正在运行,但如果使用注释掉的代码来替换,则编译器会吐出一系列错误,这些错误(如果我解释正确的话)表明 正在返回值 to 而不是从 。我怎样才能解决这个问题,使其按预期工作?谢谢.unwrap()returnstd::array::from_fnunsolved_sudoku_from_nums

/// parse nums into an UnsovedSudoku, 1-9 will be parsed as values 1-9, 0 will be parsed as an unsolved cell and all
///  other values will cause the function to return an InvalidInt error.
fn unsolved_sudoku_from_nums(nums: &[[u8; 9]; 9]) -> Result<UnsolvedSudoku, InvalidInt> {
    Ok(UnsolvedSudoku (
        std::array::from_fn(|i|{
            std::array::from_fn(|j| {
                match nums[i][j] {
                    0 => WorkingCell::PossibleValues([true; 9]),
                    int => WorkingCell::Solved(
                        SudokuValue::from_int(int)
                            .unwrap()
                            // .expect(
                            //     return Err(InvalidInt{
                            //         row: i, 
                            //         column: j, 
                            //         int: nums[i][j],
                            //     })
                            // )
                        ),
                }
            })
        })
    ))
}

仅供参考

struct UnsolvedSudoku (
    [[WorkingCell; 9]; 9]
);
函数 rust 返回

评论

0赞 kmdreko 11/5/2023
std::array::try_from_fn在这里是理想的,但不幸的是它不稳定
0赞 Pioneer_11 11/5/2023
@kmdreko是的,我知道,真的很生气,我不能使用那个。在此期间,你有什么想法吗?
0赞 cdhowie 11/5/2023
顺便说一句,将在每次调用时返回,而不仅仅是 is 或 .用作参数几乎总是错误的。它是有效的 Rust,因为表达式具有 ,可以隐式转换为任何类型,但几乎可以肯定它不会做你想做的事。x.expect(return Err(...))ErrxErrNonereturnreturn
0赞 cdhowie 11/5/2023
@Pioneer_11 是否实现和/或?WorkingCellDefaultCopy
0赞 Pioneer_11 11/5/2023
@cdhowie不,但我可以轻松实现两者,你为什么要问?

答:

1赞 cdhowie 11/7/2023 #1

如果数组中的元素类型实现了,则可以编写一个非常简单的不稳定标准库函数的实现,它不像 那样优化,但不需要不安全的代码:Defaultstd::array::try_from_fn()try_from_fn

fn array_try_from_fn<const N: usize, T, E, F>(mut f: F) -> Result<[T; N], E>
where
    T: Default,
    F: FnMut(usize) -> Result<T, E>,
{
    let mut arr = std::array::from_fn(|_| T::default());

    for i in 0..N {
        arr[i] = f(i)?;
    }

    Ok(arr)
}

这为您提供了标准库函数的人体工程学设计,并允许您在稳定时轻松更换此功能。try_from_fn

评论

1赞 Filipe Rodrigues 11/7/2023
对于更复杂的情况,其中 ,但仍然(例如)可用于创建初始数组T: !CopyT: DefaultVec<T>std::array::from_fn(|_| T::default())
0赞 Pioneer_11 11/10/2023
@FilipeRodrigues我想这确实有效,但它比我试图做的要复杂得多。我需要处理来自外部循环的内部循环的错误,然后在创建时再次处理错误,您也会误入不稳定的代码并受到很大的性能影响。它确实有效,但我看不出这样做比使用建筑物或建筑物然后调用它们有什么好处UnsolvedSudokuVecarrayvecstd::array::from_fn
0赞 cdhowie 11/10/2023
@Pioneer_11 他只是建议对我的代码进行细微的更改,以便可以删除约束。(事实上,我只是将这个建议纳入了我的回答中。T:Copy
0赞 Pioneer_11 11/11/2023
@cdhowie我明白这一点。我确信这段代码有用途,但它没有按照我的要求进行,如果我要扩展它,那么这将是一个糟糕的解决方案。因为它需要对单个错误进行三层错误处理,而且效率低下。它是用 0 填充数组并换出值的样板。
0赞 cdhowie 11/13/2023
@Pioneer_11 在你的情况下,这与你在对你的问题的评论中提到的你很生气你不能使用它的情况几乎是一样的。所以我很困惑,因为它似乎是你喜欢的解决方案,但你同时也反对它?std::array::try_from_fn