如何使用vararg案例类进行模式匹配?

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可能不适用于旧版本.

  • 我的假设是问题是关于Scala中的模式匹配而不是几何. (5认同)

Dar*_*rio 8

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)