Scala,C#相当于F#活动模式

Mar*_*cek 17 c# f# scala

F#具有使用户能够扩展模式匹配的功能:

let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd
match 3 with | Odd -> printfn "odd"
             | Even -> printfn "even"
Run Code Online (Sandbox Code Playgroud)

要么:

(** Parsing date from any of the formats: MM/DD/YY, MM/DD/YYYY, YYYY-MM-DD *)
let parseDate = function
| ParseRegex "(\d{1,2})/(\d{1,2})/(\d{1,2})$" [Integer m; Integer d; Integer y]
   -> new DateTime(y + 2000, m, d)
| ParseRegex "(\d{1,2})/(\d{1,2})/(\d{3,4})" [Integer m; Integer d; Integer y]
   -> new DateTime(y, m, d)
| ParseRegex "(\d{1,4})-(\d{1,2})-(\d{1,2})" [Integer y; Integer m; Integer d]
   -> new DateTime(y, m, d)
Run Code Online (Sandbox Code Playgroud)

神奇发生在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])
Run Code Online (Sandbox Code Playgroud)

ParseRegex现在可以在任何地方使用,它的全部意义在于可以以非常简洁的方式解析字符串的各个部分.

Scala有类似的功能吗?

在C#中,这种简洁程度似乎很难实现,但是使用隐式转换可能有些聪明的技巧可能会有所帮助吗?

Itt*_*ayD 19

免责声明:我不知道F#.

在scala中,如果值具有名为unapply(或unapplySeq)的方法,则它将用于模式匹配.

unapply的定义是:

object Example {
    def unapply(t: T): Option[(T1, ..., Tn)] = ...
}
Run Code Online (Sandbox Code Playgroud)

如果None返回则表示不匹配,Some((t1, ..., tn))表示匹配成功,可以绑定到值t1到tn

然后它可以用作:

value match {
  case Example(t1, ..., tn) => ...
}
Run Code Online (Sandbox Code Playgroud)

如果匹配可以具有动态的结果数,则unapplySeq使用返回的结果Option[List[T]]

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

例子:

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

"12/12/12" match {
   case Date(m, d, y) => ...
}
Run Code Online (Sandbox Code Playgroud)

.r方法将字符串转换为正则表达式.该类有一个unapplySeq方法,匹配正则表达式中的组.

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

somePerson match {
    case Person(name, age) => ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,语法case class创建一个具有相同名称(Person)的单例对象,其中一个unapply方法与构造函数参数匹配.

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

class BooleanExtractor[T](f: T => Boolean) { 
  def unapply(t: T) = f(t)
}
Run Code Online (Sandbox Code Playgroud)

现在,我们可以像这样使用(显示两种方式)

val Even = new BooleanExtractor[Int](_ % 2 == 0)
object Odd extends BooleanExtractor[Int](_ % 2 == 1)
Run Code Online (Sandbox Code Playgroud)

并使用:

scala> 3 match {
     |   case Even() => println("even")
     |   case Odd() => println("odd")
     | }
odd
Run Code Online (Sandbox Code Playgroud)


nul*_*ace 7

您可以通过名为Extractors的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")
}
Run Code Online (Sandbox Code Playgroud)


zig*_*tar 5

您可以在Scala中实现相同的功能.这个概念叫做Extractors.定义它们的语法比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
Run Code Online (Sandbox Code Playgroud)

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

  • 这里有很多斯卡拉人. (2认同)