活动模式

上周有人向我指出了F#中的活动模式。 这是一个非常有趣的发现。

活动模式用于F#上以对数据进行分区。 这些分区然后可以与模式匹配一​​起使用。 微软的网页将它们与有区别的工会进行了比较。

如何使用它们? 好吧,您可以看一下上面的链接,或者只是关注这篇文章(或者,实际上两者都做)。

下面是使用模式匹配的平凡函数的初始版本。

let thisNumberTrait(number) =
    match number with
        | x when x = 0 -> "Is Zero!!"
        | x when x > 0 -> "Is Positive!!"
        | x when x < 0 -> "Is Negative!!"
        | _ -> "I shouldn't be here"

上面代码的第一个改进是将逻辑放在功能后面的防护上,因此我们可以这样做:

let isZero(number) = number = 0
let isPositive(number) = number > 0
let isNegative(number) = number < 0

let thisNumberTrait(number) =
    match number with
        | x when isZero(x) -> "Is Zero!!"
        | x when isPositive(x) -> "Is Positive!!"
        | x when isNegative(x) -> "Is Negative!!"
        | _ -> "I shouldn't be here"

但是,如果我们可以完全删除保护条款呢? 这就是活动模式起作用的地方。

let (|Zero|_|) (number) = if number = 0 then Some(number) else None
let (|Positive|_|) (number) = if number > 0 then Some(number) else None
let (|Negative|_|) (number) = if number < 0 then Some(number) else None

let thisNumberTrait(number) =
    match number with
        | Zero(x) -> "Is Zero!!"
        | Positive(x) -> "Is Positive!!"
        | Negative(x) -> "Is Negative!!"
        | _ -> "I shouldn't be here"

如您所见,代码上有一些区别。 如果我们专注于逻辑函数,我们可以看到现在函数的名称已针对构造(| | |)进行了更改,现在返回的是Option类型。 然后,模式匹配将x when ...代码替换为新的Pattern Zero(x) 。 我们使功能复杂一些,简化了模式匹配。

如果我们看看提供的答案是什么,我们就会意识到我们根本没有使用数字,因此实际上我们可以更改行号

| Zero(x) -> "Is Zero!!"

对于

| Zero(_) -> "Is Zero!!"

x不是我们传递给Pattern的数据,而是返回的数据! 我们通过了数据隐含性。 但是,等等,如果我不使用返回数据,是否需要全部返回? 答案是否定的。 所以现在我们替换

let (|Zero|_|) (number) = if number = 0 then Some(number) else None

let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None

我们返回模式的名称,而不是数据。

现在这意味着在比赛中我们可以从

| Zero(_) -> "Is Zero!!"

| Zero -> "Is Zero!!"

到目前为止,我们已经返回了已传递的相同数据,但未返回任何内容。 但是,如果我们想返回其他类型的数据怎么办? 可能的:请看下面的(|Positive|_|)现在返回一个字符串。

let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
let (|Positive|_|) (number) = if number > 0 then Some("Positive") else None
let (|Negative|_|) (number) = if number < 0 then Some(number) else None

let thisNumberTrait(number) =
    match number with
        | Zero -> "Is Zero!!"
        | Positive(x) -> sprintf "Is %s!!" x
        | Negative(_) -> "Is Negative!!"
        | _ -> "I shouldn't be here"

到目前为止,我一直在使用部分模式。 即,不能将数据定义为分区。 这就是为什么下划线( (|Zero|_|) )以及为什么我们返回Option(Some | None)的原因。 但是我们可以有一个完整的活动模式,其中数据必须位于分区之一内。 更改很容易,如下所示)

let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None

let (|Zero|NonZero|) (number) = if number = 0 then Zero else NonZero

可以使用&组合模式和|来组合模式| 为或组合。

所以代替

| Positive(x) -> sprintf "Is %s!!" x

我们可以写

| NonZero & Positive(x) -> sprintg "Is %s!!" x

并非在这种情况下有任何区别,而是可能的。

最后,我们可以制作一个大图案,替换

let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
let (|Positive|_|) (number) = if number > 0 then Some(Positive) else None
let (|Negative|_|) (number) = if number < 0 then Some(Negative) else None

let (|Zero|Positive|Negative|) (number) = if number = 0 then Zero elif number > 0 then Positive else Negative

在这种情况下,对我来说似乎毫无意义,因为我几乎回到了原始代码。 它将有它的用途。

活动模式是一个有趣的结构,尤其是在多次使用活动模式时。

翻译自: https://www.javacodegeeks.com/2019/01/active-pattern.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值