tom*_*tom 13 functional-programming scala pattern-matching
我有一组像这样的案例类
abstract class Shape
case class Rectangle(width: Int, height: Int) extends Shape
case class Location(x: Int, y: Int, shape: Shape) extends Shape
case class Circle(radius: Int) extends Shape
case class Group(shape: Shape*) extends Shape
Run Code Online (Sandbox Code Playgroud)
其中基本上Group是一个形状数组.我需要定义一个大小方法来计算矩形,圆形和位置的大小,它直接只返回一个.但我对集团有困难.
object size extends Shape{
def size(s: Any) : Int = s match {
case Rectangle(x,y) => 1
case Group // how to do it? Also having case Group(shape : Shape*) gives an error
case Circle(r) => 1
case Location(x,y,shape) => 1
}
}
Run Code Online (Sandbox Code Playgroud)
我知道对于Group我需要使用map并向左折叠,但我真的无法为它创建逻辑.谢谢
ret*_*nym 17
这些中的任何一个都可以工作,第二个可能是首选,如果有点奇怪乍一看.请参阅Scala参考中的 8.1.9模式序列.
case g: Group => g.shape.map(size(_)).sum
case Group(ss @ _*) => ss.map(size(_)).sum
Run Code Online (Sandbox Code Playgroud)
这是使用Scala 2.8.sum
可能不适用于旧版本.
vararg模式匹配的语法有点奇怪.
def size(s: Shape) : Int = s match{
case Rectangle(x,y) => 1
case Circle(r) => 1
case Location(x,y,shape) => 1
case Group(shapes @ _*) => (0 /: shapes) { _ + size(_) }
}
Run Code Online (Sandbox Code Playgroud)
请注意,在最后一行中,您shapes
使用/:
折叠的注释总结所有子的大小 - 从零开始.
折叠如何工作:折叠使用给定函数累积序列的元素.
所以为了计算列表的总和,我们会写(Haskell风格)
fold (\total element -> total + element) 0 list
Run Code Online (Sandbox Code Playgroud)
它将列表的所有元素与从0开始的给定加法函数组合(因此计算总和).
在Scala中,我们可以这样写:
(0 /: list) { (total, element) => total + element }
Run Code Online (Sandbox Code Playgroud)
这可以简化为
(0 /: list) { _ + _ }
Run Code Online (Sandbox Code Playgroud)