传入运算符作为参数

时间:2015-09-25 18:59:02

标签: scala function parameters pattern-matching operators

我正在练习#34; Scala for the Impatient",Chapter 14,Q8:

基本上我需要创建一个接收运算符和节点的函数(利用模式匹配),并输出操作的结果。例如。节点(+,Node(*,Leaf(2),Leaf(3))Leaf(1))应输出7。

以下是一些给定的类:

sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree

所以我创建了一个Node类,但是我很难弄清楚如何传入运算符。

case class Node(op: Function (what goes here?) , leaves: BinaryTree*) extends BinaryTree

我想像这样使用模式匹配:

  tree match {
    case Node(op, leaves @ _*) => op match {
      case op : Function => leaves.reduceLeft(_ op _)
    }
    case leaf: Leaf => leaf.value

但是

case op : Function => leaves.reduceLeft(_ op _)

部分是错误的。我不知道如何使用在Node类中传递的运算符。我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

我假设运算符将始终是二进制因此,我们所谓的BinaryTree将至少有两个操作数:

  trait BinaryTree

  case class Leaf(value: Int) extends BinaryTree

  case class Node(op: Function2[Int, Int, Int], l1: BinaryTree*) extends BinaryTree

  object Operators {
    val + = (a: Int, b: Int) => a + b
    val * = (a: Int, b: Int) => a * b
  }

  def f(tree: BinaryTree): Int = {
    tree match {
      case n: Node => n.l1.map(f).reduceLeft((r,c) => n.op(r,c))
      case leaf: Leaf => leaf.value
    }
  }

一些测试结果:

简单的一个:

scala>   f(Node(Operators.*,Leaf(4),Leaf(2),Leaf(3)))
res4: Int = 24

scala> f(Node(Operators.+, 
         Node(Operators.*, Leaf(2), Leaf(1), Leaf(4), Leaf(5)), Leaf(6)))
res5: Int = 46

scala>   f(Node(Operators.+, 
          Node(Operators.*, Leaf(2), Leaf(1), Leaf(4), Leaf(5)),
          Node(Operators.+,Leaf(9),Leaf(9)), Leaf(6)))
res6: Int = 64

相当复杂:

scala> f(Node(Operators.+,
          Node(Operators.*, Leaf(2), Leaf(1), 
          Node(Operators.* ,Leaf(4), Leaf(5) ,Leaf(2))),
          Node(Operators.+,Leaf(9),Leaf(9)), Leaf(6),
          Node(Operators.*, Leaf(2), Leaf(2))))
res7: Int = 108

答案 1 :(得分:2)

它有更优雅的解决方案,但因为你想要它与模式匹配:

sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(op: (Int, Int) => Int , leaves: BinaryTree*) extends BinaryTree

def calc(tree: BinaryTree): Int = tree match {
  case Leaf(v) => v
  case Node(op, h, leaves @ _*) => leaves.foldLeft(calc(h))((a,b) => op(a,calc(b)))
}

object Operators {
  def +(a: Int, b: Int): Int = a + b
  def *(a: Int, b: Int): Int = a * b
}

val tree = Node(Operators.+, Node(Operators.*, Leaf(9), Leaf(3)), Leaf(1))

calc(tree)