Scala,C#等效于F#活动模式

Scala,C#等效于F#活动模式,c#,scala,f#,C#,Scala,F#,F#具有一项功能,允许用户扩展模式匹配: let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd match 3 with | Odd -> printfn "odd" | Even -> printfn "even" 或: 神奇之处在于ParseRegex模式,其定义如下: (** Definition of the MatchRegex active pattern *) let (|ParseRege

F#具有一项功能,允许用户扩展模式匹配:

let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd
match 3 with | Odd -> printfn "odd"
             | Even -> printfn "even"
或:

神奇之处在于ParseRegex模式,其定义如下:

(** Definition of the MatchRegex active pattern *)
let (|ParseRegex|_|) rgx s = match Regex(rgx).Match(s) with
                         | m when not m.Success -> None
                         | m -> Some(List.tail [for x in m.Groups->x.Value])
ParseRegex现在可以在任何地方使用,其要点是可以以非常简洁的方式解析字符串的各个部分

Scala有类似的特性吗


在C语言中,这种简洁程度似乎很难实现,但也许一些使用隐式转换的巧妙技巧会有所帮助?

您可以通过一个名为的scala功能来实现这一功能

对于偶数/奇数示例:

object Even {
  def unapply(x:Int) = if (x % 2 == 0) Some(x) else None
}

object Odd {
  def unapply(x:Int) = if (x % 2 == 1) Some(x) else None
}

3 match {
  case Even(x) => println("even")
  case Odd(x) => println("odd")
}
免责声明:我不知道F

在scala中,如果一个值有一个名为unapply(或unapplySeq)的方法,那么它将用于模式匹配

取消应用的定义是:

object Example {
    def unapply(t: T): Option[(T1, ..., Tn)] = ...
}
如果返回
None
,则表示不匹配,
Some((t1,…,tn))
表示匹配成功,并且可以绑定到值t1到tn

然后它可以用作:

value match {
  case Example(t1, ..., tn) => ...
}
如果匹配可以有动态数量的结果,则使用
unplyseq
,返回
选项[List[T]]

最后,如果匹配时不需要绑定变量,unapply可以只返回一个布尔值

示例:

val Date = ""(\d{1,2})/(\d{1,2})/(\d{1,2})$".r

"12/12/12" match {
   case Date(m, d, y) => ...
}
.r
方法将字符串转换为正则表达式。该类有一个unallyseq方法,该方法与正则表达式中的组相匹配

case class Person(name: String, age: Int)

somePerson match {
    case Person(name, age) => ...
}
在本例中,语法
case类
使用与构造函数参数匹配的unapply方法创建具有相同名称(Person)的单例对象

更新:下面是如何定义偶数和奇数 首先是一些概括。偶数和奇数都可以通过函数表示,但是我们需要使这个函数符合提取器规范,也就是说,通过unapply应用它

class BooleanExtractor[T](f: T => Boolean) { 
  def unapply(t: T) = f(t)
}
现在,我们可以这样使用(显示两种方式)

和使用:

scala> 3 match {
     |   case Even() => println("even")
     |   case Odd() => println("odd")
     | }
odd

您可以在Scala中实现同样的效果。这个概念被称为提取器。定义它们的语法似乎比F#中的要难看一些。我将提供第一个示例:

scala> object Even {def unapply(z: Int) = (z%2 == 0)}                      
defined module Even    
scala> object Odd {def unapply(z: Int) = (z%2 != 0)}                       
defined module Odd    
scala> 2 match {
     | case Even() => "even";
     | case Odd() => "odd";
     | }
res10: java.lang.String = even

你的第二个例子也有效。必须从unapply方法返回DateTime对象。我提供了一个链接,您可以在其中阅读更多有关该主题的内容。

我注意到没有人为此添加C#代码,因此我尝试在这里复制代码中的功能: 基本上,我创建了一个或两个助手类,然后可以编写如下代码:

var apInt = Option<int>.From<string>(s =>
{
    int i;
    return System.Int32.TryParse(s, out i) 
        ? new Option<int>(i) 
        : Option<int>.Empty;
});

var apBool = Option<bool>.From<string>(s =>
{
    bool b;
    return System.Boolean.TryParse(s, out b)
        ? new Option<bool>(b)
        : Option<bool>.Empty;
});

var testParse = new Action<string>(s =>
{
    FluidFunc
        .Match(s)
        .With(apInt, r => Console.WriteLine($"The value is an int '{r}'"))
        .With(apBool, r => Console.WriteLine($"The value is an bool '{r}'"))
        .Else(v => Console.WriteLine($"The value '{v}' is something else"));
});

testParse("12");
testParse("true");
testParse("abc");
var-apInt=Option.From(s=>
{
int i;
返回系统.Int32.TryParse(s,out i)
?新方案(i)
:选项。空;
});
var apBool=Option.From(s=>
{
布尔b;
返回系统.Boolean.TryParse(s,out b)
?新方案(b)
:选项。空;
});
var testParse=新操作=>
{
FluidFunc
.比赛
.With(apInt,r=>Console.WriteLine($“该值是一个int'{r}'))
.With(apBool,r=>Console.WriteLine($“值是bool'{r}'))
.Else(v=>Console.WriteLine($“值“{v}”是其他内容”);
});
testParse(“12”);
testParse(“真”);
测试解析(“abc”);

doh,在发布之前我也刷新了。谢谢!所有的安瓦尔人都很好。我接受这个,因为我从中学到了很多。这很好,但我可以把它们结合起来。例如case Even()&&produceOftree(),因此在本例中6可能是第一个true,然后是Scala中的12个ect?提取器。C#甚至没有可比性,它甚至没有模式匹配。。。
scala> object Even {def unapply(z: Int) = (z%2 == 0)}                      
defined module Even    
scala> object Odd {def unapply(z: Int) = (z%2 != 0)}                       
defined module Odd    
scala> 2 match {
     | case Even() => "even";
     | case Odd() => "odd";
     | }
res10: java.lang.String = even
var apInt = Option<int>.From<string>(s =>
{
    int i;
    return System.Int32.TryParse(s, out i) 
        ? new Option<int>(i) 
        : Option<int>.Empty;
});

var apBool = Option<bool>.From<string>(s =>
{
    bool b;
    return System.Boolean.TryParse(s, out b)
        ? new Option<bool>(b)
        : Option<bool>.Empty;
});

var testParse = new Action<string>(s =>
{
    FluidFunc
        .Match(s)
        .With(apInt, r => Console.WriteLine($"The value is an int '{r}'"))
        .With(apBool, r => Console.WriteLine($"The value is an bool '{r}'"))
        .Else(v => Console.WriteLine($"The value '{v}' is something else"));
});

testParse("12");
testParse("true");
testParse("abc");