递归函数如果语句中的语句不匹配类型

时间:2016-05-31 19:41:09

标签: recursion types rust

fn recursive_binary_search<T: Ord>(list: &mut [T], target: T) -> bool {
    if list.len() < 1 {
        return false;
    }
    let guess = list.len() / 2;
    if target == list[guess] {
        return true;
    } else if list[guess] > target {
        return recursive_binary_search(&mut list[0..guess], target);
    } else if list[guess] < target {
        return recursive_binary_search(&mut list[guess..list.len()], target);
    }
}

编译器在if target == list[guess]

时抛出错误
src/main.rs:33:5: 39:6 error: mismatched types [E0308]
src/main.rs:33     if target == list[guess] {
                   ^
src/main.rs:33:5: 39:6 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:33:5: 39:6 note: expected type `bool`
src/main.rs:33:5: 39:6 note:    found type `()`
error: aborting due to previous error

我无法弄清楚如何重写此函数以满足类型检查器。我假设这是因为我将返回类型设置为bool并且有一个返回函数调用?

2 个答案:

答案 0 :(得分:5)

这里的问题是Rust将if/else if/else if评估为返回值,因为它缺少else子句,而且没有评估任何值的语句值的类型为()。顺便提一下,您提供的代码详尽地涵盖了所有可能性(切片的当前索引处的项目等于,小于或大于目标),但编译器并不知道除非你在最后给它一个else条款:

fn recursive_binary_search<T: Ord + Eq>(list: &[T], target: T) -> bool {
    if list.len() < 1 {
        return false;
    }
    let guess = list.len() / 2;
    if target == list[guess] {
        return true;
    } else if list[guess] > target {
        return recursive_binary_search(&list[0..guess], target);
    } else {
        return recursive_binary_search(&list[guess..list.len()], target);
    }
}

PS:此功能不需要可变引用,因此我建议使用常规引用,如上面的代码所示。

编辑:对于子孙后代,这里的代码没有明确的回报:

fn recursive_binary_search<T: Ord>(list: &[T], target: T) -> bool {
    if list.len() < 1 {
        return false;
    }
    let guess = list.len() / 2;
    if target == list[guess] {
        true
    } else if list[guess] > target {
        recursive_binary_search(&list[0..guess], target)
    } else {
        recursive_binary_search(&list[guess..list.len()], target)
    }
}

答案 1 :(得分:5)

dikaiosune's answer解释了问题:if生成的()类型为bool,而不是fn recursive_binary_search<T: Ord + Eq>(list: &[T], target: T) -> bool { if list.len() < 1 { return false; } let guess = list.len() / 2; if target == list[guess] { true } else if list[guess] > target { recursive_binary_search(&list[0..guess], target) } else { recursive_binary_search(&list[guess..list.len()], target) } }

以下是一些用惯用法编写代码的方法:

我首先用隐式回报写作:

match

然后我只执行一次比较,而不是两次。如果比较费用昂贵可以节省一些时间,但use std::cmp::Ordering; fn recursive_binary_search<T: Ord + Eq>(list: &[T], target: T) -> bool { if list.is_empty() { return false; } let guess = list.len() / 2; match target.cmp(&list[guess]) { Ordering::Less => recursive_binary_search(&list[..guess], target), Ordering::Greater => recursive_binary_search(&list[guess..], target), Ordering::Equal => true, } } 看起来也不错:

is_empty

您也可以删除范围的开头和结尾部分,并使用use std::cmp::Ordering; fn recursive_binary_search<T: Ord>(list: &[T], target: T) -> bool { if list.is_empty() { return false; } let guess = list.len() / 2; match target.cmp(&list[guess]) { Ordering::Less => recursive_binary_search(&list[..guess], target), Ordering::Greater => recursive_binary_search(&list[guess+1..], target), Ordering::Equal => true, } } fn main() { assert!(!recursive_binary_search(&[1,2,3,4,5], 0)); assert!(recursive_binary_search(&[1,2,3,4,5], 1)); assert!(recursive_binary_search(&[1,2,3,4,5], 2)); assert!(recursive_binary_search(&[1,2,3,4,5], 3)); assert!(recursive_binary_search(&[1,2,3,4,5], 4)); assert!(recursive_binary_search(&[1,2,3,4,5], 5)); assert!(!recursive_binary_search(&[1,2,3,4,5], 6)); } 作为保护条款。

如果你搜索一个大于最大值的值,那么堆栈溢出的问题......你需要在重复时忽略这个数据集:

postHeight

如果您为实现学习目的而实施此功能,请使用内置的binary_search