【问题标题】:F# Weird pattern matching resultF# 奇怪的模式匹配结果
【发布时间】:2016-01-03 11:48:15
【问题描述】:

我正在编写二进制搜索实现。我遇到的问题是模式匹配块。

此代码使用模式匹配返回奇怪的结果。第一个匹配块没有返回我所期望的。它警告我永远无法到达(_,_)

let binSearch (item:double) (arr:list<double>) =
    let rec binSearchRec first last =
        if first > last then
            let lastIndex = arr.Length-1
            let len = arr.Length
            match (first, last) with
            | (0, -1) -> System.String.Format("ITEM SMALLER THAN {0}", arr.[0])
            | (len, lastIndex) -> System.String.Format("ITEM BIGGER THAN {0}", arr.[lastIndex])
            | (_,_) -> System.String.Format("IN BETWEEN {0} AND {1}", arr.[last], arr.[first])
        else
            let mid = (first+last)/2
            match item.CompareTo(arr.[mid]) with
            | -1 -> binSearchRec first (mid-1)
            | 0 -> "CONTAINS"
            | 1 -> binSearchRec (mid+1) last
    binSearchRec 0 (arr.Length-1)

用这个 if-else 替代方法替换第一个 match (first, last) 调用效果很好:

if first = 0 && last = -1 then
    System.String.Format("ITEM SMALLER THAN {0}", arr.[0])
else if first = len && last = lastIndex then
    System.String.Format("ITEM BIGGER THAN {0}", arr.[lastIndex])
else
    System.String.Format("IN BETWEEN {0} AND {1}", arr.[last], arr.[first])

我不明白 match 调用与 if-else 调用有何不同,以及为什么它运行良好但模式匹配块没有。

一个奇怪的结果是在 (len, lastIndex) 匹配中打印 len 在匹配中返回错误的数字。对于长度为 3 的数组,在 match 语句之前打印 len 将显示 3,而在 match 内部打印将显示 1。

【问题讨论】:

    标签: f#


    【解决方案1】:

    匹配表达式中的一个分支是创建与现有符号的新绑定

    | (len, lastIndex) -> ...
    

    所以这个分支与其他所有情况都匹配。

    如果你要匹配匹配表达式中的现有值,你可以使用 when clase for that:

    | (a, b) when a = len && b = lastIndex -> ...
    

    另一种选择是将 lenlastIndex 声明为文字以在模式匹配中使用它们,但在您的情况下似乎不自然。

    [<Literal>]
    let len = arr.Length
    

    【讨论】:

    • 在这种情况下无论如何都不能使用文字,你只能将它用于文字值,而不是像arr.Length这样的运行时值。
    猜你喜欢
    • 1970-01-01
    • 2020-08-21
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多