F#奇怪模式匹配结果
问题描述:
我正在编写二分查找实现。我遇到的问题是模式匹配块。F#奇怪模式匹配结果
此代码使用模式匹配返回奇怪的结果。第一个匹配块不会返回我所期望的。它警告我永远不会到达(_,_)
。
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)
更换,首先match (first, last)
电话本的if-else替代效果很好:
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])
我不明白,那场比赛通话的此不同的if-else呼叫,为什么这个效果很好但模式匹配块没有。
一个奇怪的结果是打印在(len, lastIndex)
匹配len在匹配返回错误的数字。对于长度为3的数组len
比赛语句之前打印将显示3,而在比赛中的打印将显示1
答
一个在比赛表达你的分支正在创造新的绑定到现有符号
| (len, lastIndex) -> ...
所以这个分支与其他情况相匹配。
如果你去匹配在匹配表达式现有值你可以使用时CLASE为:
| (a, b) when a = len && b = lastIndex -> ...
另一种办法是宣布len个和lastIndex的作为文字在模式匹配使用它们但在你的情况下似乎并不自然。
[<Literal>]
let len = arr.Length
无论如何,在这种情况下不能使用文字,你只能将它用于字面值,而不是像'arr.Length'这样的运行时值。 – Tarmil