F#奇模式匹配问题

F#奇模式匹配问题,f#,pattern-matching,F#,Pattern Matching,昨天在编写代码时,我遇到了两个奇怪的问题,我和我的面向函数编程的朋友都无法解决。我们已经研究了很长一段时间,并在网上进行了研究,但我们在任何地方都找不到任何答案,因此: 问题在于,在本规范中: 第一个奇怪的问题: let outer1 (bs : byte array) = let rec inner (bs : byte array) (bacc : byte array) (i : int) = match i with | bs.Length -&g

昨天在编写代码时,我遇到了两个奇怪的问题,我和我的面向函数编程的朋友都无法解决。我们已经研究了很长一段时间,并在网上进行了研究,但我们在任何地方都找不到任何答案,因此:

问题在于,在本规范中:

第一个奇怪的问题:

let outer1 (bs : byte array) =
    let rec inner (bs : byte array) (bacc : byte array) (i : int) =
        match i with
        | bs.Length -> bacc // <--- Error: bs is not recognized. Why?
        | _ -> bacc.[i] <- bs.[i]
               inner bs bacc (i + 1)
    inner bs (Array.zeroCreate bs.Length) 0
这里的问题是警告:
警告FS0026:此规则永远不会匹配

我一点也不明白
i
和数组的长度彼此没有关系。如果我写一个整数(例如
10
)而不是
bsLength
,警告就会消失。

匹配语句的工作方式与您认为的不同-正确的语法是

match i with
| t when t = bs.Length

在第二种情况下,您实际上创建了一个名为
bsLength
的新变量,该变量隐藏了早期
bsLength
的定义并匹配所有整数,因此您会得到规则从不匹配警告。

这两个问题都源于模式匹配允许互换使用值和文字的期望。不,没有。MSDN上的主题很好地概述了受支持的模式类型及其应用程序的优先级规则。简化冗长描述的主要原则是:除非该值是文本标识符(区分并集的大小写值、异常标签或活动模式大小写),否则无法匹配值

在您的第一个问题点中,编译器不会像您期望的那样将
bs.Length
视为数组
bs
的属性
Length
,而是将其视为来自不存在的模块或命名空间
bs
的文本或标识符
Length
;正如他在回答中所指出的那样,您可以通过使用带有。与您相似的模式匹配表达式的合法使用示例如下:

module bs =
    [<Literal>]
    let Length = 100
//.............................
let v = 100;
let s = match v with
    | bs.Length -> "matched"
    | _ -> "not matched";;

val s : string = "matched"
模块bs=
[]
设长度=100
//.............................
设v=100;
让s=与v匹配
|bs.长度->“匹配”
|->“不匹配”;;
val s:string=“匹配”

编译器将第二个问题点视为变量模式,
bsLength
被赋值为
i
,而不是像您所期望的那样进行比较;第二条匹配规则没有机会生效。

谢谢你澄清了这一点。我现在更改了代码,它可以工作了。而且,现在终于明白问题出在哪里了,这很好。你的回答很好。:)谢谢,一个简单但切中要害的答案。:)回答得好!我现在理解了这个问题,因为我知道它正在创建一个新的变量
module bs =
    [<Literal>]
    let Length = 100
//.............................
let v = 100;
let s = match v with
    | bs.Length -> "matched"
    | _ -> "not matched";;

val s : string = "matched"