F#奇数模式匹配问题 [英] F# odd pattern matching issues

查看:117
本文介绍了F#奇数模式匹配问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天写一些代码时,我遇到了两个奇怪的问题,我和面向功能编程的朋友都无法解决.我们已经看了很长时间,并在网上对其进行了研究,但是我们无法在任何地方找到任何答案,所以去了:

While writing some code yesterday, I ran into two odd problems, which neither me nor my functional programming oriented friend could figure out. We have looked at it for quite some time, and researched it on the net, but we were not able to find any answers anywhere, so here goes:

问题在于此代码中:

第一个奇怪的问题:

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

这里的问题是:FS0039: The namespace or module 'bs' is not defined. 怎么会这样? bs毕竟在功能签名中.此外,用let bsLength = bs.Length定义新值的工作就在match之前.但是这样做,我看到了一个新的奇怪之处:<​​/p>

The problem here is: FS0039: The namespace or module 'bs' is not defined. How can this be? bs is in the function signature after all. Moreover, defining a new value with let bsLength = bs.Length works right before the match. But by doing so I see a new oddity:

let outer2 (bs : byte array) =
    let rec inner (bs : byte array) (bacc : byte array) (i : int) =
        let bsLength = bs.Length
        match i with
        | bsLength -> bacc
        | _ -> bacc.[i] <- bs.[i] // <--- Warning: Rule never matched. Why?
               inner bs bacc (i + 1)
    inner bs (Array.zeroCreate bs.Length) 0

这里的问题是一个警告,提示:warning FS0026: This rule will never be matched. 我一点都不明白. i与数组的长度互不相关.如果我写一个整数(例如10)而不是bsLength,则警告消失.

Here the problem is a warning that says: warning FS0026: This rule will never be matched. I don't get that at all. i and the length of the array has no relation to each other. If I write an integer (for instance 10) instead of bsLength, the warning disappears.

推荐答案

这两个问题都源于人们期望模式匹配可以互换使用值和文字.不,不是的. MSDN上的模式匹配(F#)主题很好地概述了受支持的模式类型及其应用的优先规则.简化冗长说明的主要原则是:除非该值是 literal identifier (有区别的并集的案例值,异常标签),否则您无法匹配值,或活动模式案例).

Both your problems stem from the expectation that pattern matching allows using values and literals interchangeably. No, it does not. Pattern Matching (F#) topic on MSDN gives a good overview of supported pattern types and precedence rules of their application. The major principle simplifying a lengthy description there is: you cannot match a value unless this value is a literal, or identifier (a case value of a discriminated union, an exception label, or an active pattern case).

在第一个问题点,编译器不会将bs.Length视为您期望的数组bs的属性Length,而是将其视为不存在的模块或命名空间bs的文字或标识符Length;正如 John Palmer 指出的那样,您可以使用 variable 模式实现预期的行为带有保护声明.合法使用类似于您的模式匹配表达式的示例为:

In your first problem point compiler treats bs.Length not as a property Length of array bs as you expect, but as a literal or identifier Length from non-existing module or namespace bs; as John Palmer pointed in his answer you may achieve the expected behavior by using variable pattern with a guard statement. A sample of legitimate use of the pattern matching expression resembling yours would be:

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

val s : string = "matched"

编译器将第二个问题点视为变量模式,并且为bsLength分配了一个i值,而不是按照您的预期进行比较;第二个匹配规则没有机会加入.

The second problem point is treated by compiler as variable pattern, and bsLength is assigned a value of i instead of values being compared, as you expected; second matching rule does not have chances to kick in.

这篇关于F#奇数模式匹配问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆