Dan*_*iel 1 f# pattern-matching active-pattern
如果普通函数可以用作模式,则可以节省必须编写琐碎的活动模式,如
let (|NotEmpty|_|) s = Seq.tryPick Some s
Run Code Online (Sandbox Code Playgroud)
并且假设允许
let s = seq []
match s with
| Seq.tryPick Some -> ...
| _ -> //empty
Run Code Online (Sandbox Code Playgroud)
这将使函数更具可重用性,无需使用匹配的"模式化"函数:
let f x = if x then Some() else None
let (|F|_|) = f
Run Code Online (Sandbox Code Playgroud)
我知道活动模式可以被称为函数,因此可以通过仅定义模式来简化前面的示例.但是,放弃特殊模式语法简化了这一点.
特殊语法的原因是什么?
在下文中,活动模式会影响文字.
[<Literal>]
let X = 1
let (|X|_|) x = if x = 0 then Some() else None
match 0 with //returns true
| X -> true
| _ -> false
Run Code Online (Sandbox Code Playgroud)
为什么在模式中函数调用也不起作用?
我发现了一个模棱两可的场景
let zero n = if n = 0 then Some() else None
match 0 with
| zero -> //function call or capture?
Run Code Online (Sandbox Code Playgroud)
在我看来,这清楚地说明了为什么活动模式必须以大写字母开头 - 它使意图更清晰并且使阴影(例如在我之前的示例中)更不可能.
回答这个问题的一种方法是说活动模式(作为一种特殊的句法类别)可以使用相同的名称在表达式中构造值并在模式中解构它.
例如,假设我们使用一种类型Info来表示一些信息:
type Info = I of string * int
Run Code Online (Sandbox Code Playgroud)
您可以编写两个函数来构造和销毁此类型的值:
val constructInfo : string * int -> Info
val destructInfo : Info -> string * int
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这两个函数很容易实现,但有趣的是它们的类型签名是双重的.构造获取值并创建我们的(抽象)类型,销毁获取类型并返回单个值.
使用活动模式,我们可以使用相同的名称Info,用于这两个目的.这使得它与语言的其余部分保持一致 - 例如x::xs,(a, b)它们都是构造函数和模式.F#库对F#引用做了类似的事情(即Lambda类型的模式和构造函数都是如此Expr.
因此,我们可以定义一个函数和一个模式,而不是编写构造和破坏函数:
let Info (a, b) = I (a, b)
let (|Info|) (I (a, b)) = (a, b)
Run Code Online (Sandbox Code Playgroud)
结果是,相同的语法Info(a, b)可以作为模式和表达式出现.
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |