Scala Extractor with Argument

Fys*_*ysx 9 f# scala pattern-matching active-pattern extractor

Scala中是否存在允许提取器采用自定义参数的语法?这个例子有点人为.假设我在整数上有一个二叉搜索树,如果它的值可以被某个自定义值整除,我想匹配当前节点.

使用F#活动模式,我可以执行以下操作:

type Tree =
    | Node of int * Tree * Tree
    | Empty  

let (|NodeDivisibleBy|_|) x t =
    match t with
    | Empty -> None
    | Node(y, l, r) -> if y % x = 0 then Some((l, r)) else None

let doit = function
    | NodeDivisibleBy(2)(l, r) -> printfn "Matched two: %A %A" l r
    | NodeDivisibleBy(3)(l, r) -> printfn "Matched three: %A %A" l r
    | _ -> printfn "Nada"

[<EntryPoint>]
let main args =
    let t10 = Node(10, Node(1, Empty, Empty), Empty)
    let t15 = Node(15, Node(1, Empty, Empty), Empty)

    doit t10
    doit t15

    0
Run Code Online (Sandbox Code Playgroud)

在Scala中,我可以做类似的事情,但不是我想要的:

sealed trait Tree
case object Empty extends Tree
case class Node(v: Int, l: Tree, r: Tree) extends Tree

object NodeDivisibleBy {
  def apply(x: Int) = new {
    def unapply(t: Tree) = t match { 
      case Empty => None
      case Node(y, l, r) => if (y % x == 0) Some((l, r)) else None
    }
  }
}

def doit(t: Tree) {
  // I would prefer to not need these two lines.
  val NodeDivisibleBy2 = NodeDivisibleBy(2)
  val NodeDivisibleBy3 = NodeDivisibleBy(3)
  t match { 
    case NodeDivisibleBy2(l, r) => println("Matched two: " + l + " " + r)
    case NodeDivisibleBy3(l, r) => println("Matched three: " + l + " " + r)
    case _ => println("Nada")
  }
}

val t10 = Node(10, Node(1, Empty, Empty), Empty)
val t15 = Node(15, Node(1, Empty, Empty), Empty)

doit(t10)
doit(t15)
Run Code Online (Sandbox Code Playgroud)

如果我能这样做会很棒:

case NodeDivisibleBy(2)(l, r) => println("Matched two: " + l + " " + r)
case NodeDivisibleBy(3)(l, r) => println("Matched three: " + l + " " + r)
Run Code Online (Sandbox Code Playgroud)

但这是一个编译时错误:'=>'预期但是'('找到了.

思考?

Tra*_*own 6

规格:

   SimplePattern ::= StableId ‘(’ [Patterns] ‘)’
Run Code Online (Sandbox Code Playgroud)

提取器模式x(p1,...,pn),其中n≥0与构造函数模式具有相同的句法形式.但是,稳定标识符x表示一个对象,它具有一个名为unapplyunapplySeq匹配该模式的成员方法,而不是一个案例类.

和:

稳定标识符是在标识符结束的路径.

即,不是表达式NodeDivisibleBy(2).

所以不,这在Scala中不可能以任何直接的方式进行,我个人认为这很好:必须编写以下内容(顺便说一下我可能在NodeDivisibleBy对象中定义并导入):

val NodeDivisibleBy2 = NodeDivisibleBy(2)
val NodeDivisibleBy3 = NodeDivisibleBy(3)
Run Code Online (Sandbox Code Playgroud)

对于不必破解case子句中的任意表达式而言,增加的可读性是一个很小的代价.


Tim*_*een -1

据我所知,答案是否定的。

对于这种情况,我也使用以前的方法。