织梦网站专题模板下载,几百块钱可以做网站吗,产品vi设计哪家好,如何做原创小说网站F#中主动模式的三种形式
F#中有一种特殊的模式匹配#xff0c;叫做主动模式#xff08;Active Pattern#xff09;。主动模式可以让我们自定义模式匹配的方式#xff0c;这样可以让我们的代码更加简洁#xff0c;更加清晰。主动模式有三种形式#xff0c;分别是#xf…F#中主动模式的三种形式
F#中有一种特殊的模式匹配叫做主动模式Active Pattern。主动模式可以让我们自定义模式匹配的方式这样可以让我们的代码更加简洁更加清晰。主动模式有三种形式分别是
单选项主动模式多选项主动模式部分应用的主动模式
这三个方式的语法如下
let (|ActivePattern|) [parameters] valueToMatch if condition then Some ()else Nonelet (|ActivePattern1|ActivePattern2|...|) [parameters] valueToMatch match valueToMatch with| .. - ActivePattern1| .. - ActivePattern2| .. - ...let (|ActivePattern|_|) [parameters] valueToMatch if v p1 then Some (p2, ..., pn)else None从最后一个开始说起
模式匹配的本质
从语义上来看模式匹配实现的是两个部分的功能匹配检查值绑定。匹配检查就是检查值是否符合模式值绑定就是把值绑定到模式中的变量上。模式匹配的本质就是这两个功能的组合。
例子一
先看下面的例子
open Systemlet (|Int|_|) str match Int32.TryParse(str:string) with| (true, i) - Some i| _ - Nonelet (|Float|_|) str match Double.TryParse(str:string) with| (true, i) - Some i| _ - Nonelet (|Bool|_|) str match Boolean.TryParse(str:string) with| (true, i) - Some i| _ - Nonelet testParse str match str with| Int i - printfn $Int: %d{i}| Float f - printfn $Float: %f{f}| Bool b - printfn $Bool: %b{b}| _ - printfn $Not a number/bool %A{str}testParse 123
testParse 123.45
testParse true
testParse abc这个例子的功能非常简单就是识别一个字符串的内容这里实现了三个模式整数、浮点数和布尔值。然后我们可以用这三个模式来匹配字符串如果匹配成功就打印出来。匹配不成功则打印对应的消息。
从这个例子我们可以窥见主动模式的内涵以第一个模式为例。这个定义非常类似于定义了一个函数函数名称是(|Int|_|)函数的标识可以通过在fsi中输入这个这个名称来查看val ( |Int|_| ) : str:string - int option。是一个输入变量为字符串输出变量为int option类型。
我们可以直接在fsi中调用这个函数(|Int|_|) 123返回值为Some 123当字符串不是整数时返回值为None。
那么把这个函数作为一个模式来匹配时匹配成功就是返回Some 123匹配不成功就是返回None。模式匹配的第二功能是绑定那么这里的绑定就是把123绑定到i上这样就可以在模式匹配的后面使用i了。
这里很好的揭示了部分匹配的语法和语义。上面的例子也很好的展示了部分匹配的用法。如果配合正则表达式功能还可以实现更有意思的功能。
例子二
open System.Text.RegularExpressionslet (|FirstMatch|_|) pattern str let matches Regex.Matches(str, pattern)if matches.Count 0 then Some matches.[0] else Nonelet getPhoneNumber str match str with| FirstMatch 1[0-9]{10} phone - printfn $Phone: %A{phone.Value}| FirstMatch [0-9]{6,8} phone - printfn $Short phone: %A{phone.Value}| _ - printfn $Not a phone number %A{str}getPhoneNumber 13981156789
getPhoneNumber 12345678这个例子里面FirstMatch模式匹配的第一个参数是正则表达式第二个参数是要匹配的字符串。如果匹配成功就返绑定第一个匹配字符串否则返回None。
利用这个主动模式就能实现对1打头11为手机号码和6-8位电话号码的识别。这里同样是实现了匹配和绑定两个语义。绑定的对象同样是Option对象的Value。唯一不同的是这个模式还需要一个输入参数也就是正则表达式。
通过这两个例子我们可以看到部分匹配的语法和语义。比较清晰对于实际的应用也非常有用。
单选项主动模式和多选项主动模式
对于单选项主动模式和多选项主动模式与部分匹配的主动模式不同之处在于没有那个|_|缺省匹配的项。
看这部分的文档时我的第一感觉是这两个模式没有太大作用。毕竟匹配在F#的模式匹配中已经有非常方便的功能。为什么还需要通过主动模式来实现呢
毕竟这两个主动模式的绑定部分的功能并没有太大的优势。我们先来看官方文档中提供的例子。
单选项主动模式
这个模式的例子是提取System.Drawing.Color的RGB值。
open System.Drawing
let (|RGB|) (c:Color) (c.R, c.G, c.B)let printRGB c match c with| RGB (r,g,b) - printfn $RGB: %d{r}, %d{g}, %d{b}可以看到这个例子中匹配的成分很少更多的是提取和绑定。通过主动模式通过参数计算得到一个元组然后在match中绑定到三个名称上。
这里的计算和返回值可以任意的复杂因为与前面的部分匹配一样(|RGB|)同样是一个函数这个函数的输入和输出可以是任意类型这个函数的计算过程也可以是任意复杂的。
最终应用match的时候也能够得到非常清晰的语法和语义特征。并且在这个例子中IDE和编译器都能够提供非常好的支持。
结论单选项主动模式的主要作用是提取被匹配对象的信息构成新的对象然后在match中进行绑定。这在语义上非常有一致性匹配对象的部分信息然后绑定到名称上。
多选项主动模式
与单选项主动模式相反多选项主动模式更注重的是匹配而非提取绑定。
let (|Even|Odd|) i if i % 2 0 then Even else Oddlet printEvenOrOdd i match i with| Even - printfn $Even: %d{i}| Odd - printfn $Odd: %d{i}这里match调用的对象i在不同的分支中直接引用而没有进行值的转换和绑定。这里的主动模式主要是为了匹配而不是为了绑定。
多选项主动模式类似于enum只是这个enum的值是在运行时计算的。这个计算过程可以是任意复杂的只要最终返回的是一个enum值就可以了。
总结
主动模式是F#中非常有意思的一个特性。它的语法和语义都非常清晰而且非常有用。在实际的应用中可以大大的提高代码的可读性和可维护性。