传入运算符作为参数
Passing in An Operator as a Parameter
我正在做 "Scala for the Impatient" 第 14 章第 8 题的练习:
本质上,我需要创建一个函数(利用模式匹配)接收运算符和节点,并输出运算结果。例如。 Node(+, Node(*, Leaf(2), Leaf(3)) Leaf(1)) 应该输出 7.
这里有一些给定的 classes:
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
所以我创建了一个节点 class,但我很难弄清楚如何传入运算符。
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 _)
部分错误。我不知道如何使用在节点 class 中传递的运算符。我在这里做错了什么?
我假设运算符将始终是二进制的,因此,我们所谓的 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
它有更优雅的解决方案,但由于您需要模式匹配:
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)
我正在做 "Scala for the Impatient" 第 14 章第 8 题的练习:
本质上,我需要创建一个函数(利用模式匹配)接收运算符和节点,并输出运算结果。例如。 Node(+, Node(*, Leaf(2), Leaf(3)) Leaf(1)) 应该输出 7.
这里有一些给定的 classes:
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
所以我创建了一个节点 class,但我很难弄清楚如何传入运算符。
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 _)
部分错误。我不知道如何使用在节点 class 中传递的运算符。我在这里做错了什么?
我假设运算符将始终是二进制的,因此,我们所谓的 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
它有更优雅的解决方案,但由于您需要模式匹配:
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)