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

时间:2010-02-16 17:22:18

标签: scala functional-programming 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

其中基本上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   
  }  
}  

我知道Group我需要使用map并向左折叠,但我真的无法为它创建逻辑。 感谢

5 个答案:

答案 0 :(得分:17)

其中任何一个都可行,第二个可能是首选,如果有点奇怪乍一看。请参阅Scala Reference中的8.1.9模式序列。

case g: Group => g.shape.map(size(_)).sum

case Group(ss @ _*) => ss.map(size(_)).sum

这是使用Scala 2.8。 sum可能不适用于旧版本。

答案 1 :(得分:8)

vararg模式匹配的语法有点strange

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(_) }
}

请注意,在最后一行中,您使用shapes - 折叠符号来总结所有子/:的大小,从零开始。


folds如何工作:折叠使用给定函数累积序列的元素。

因此,为了计算列表的总和,我们将编写(Haskell样式)

fold (\total element -> total + element) 0 list

将列表的所有元素与从0开始的给定加法函数组合(因此计算总和)。

在Scala中,我们可以这样写:

(0 /: list) { (total, element) => total + element }

可以简化为

(0 /: list) { _ + _ }

答案 2 :(得分:2)

第一步是搞清楚你的​​意思。两个最明显的选择是所有形状覆盖的总面积,以及包含它们的最小矩形。如果对于圆圈你返回实际区域,你可能需要去实际区域。

没有封闭形式的方式来回答这个问题。我可能会考虑在最小的封闭矩形上投掷一千个随机飞镖并将该区域估计为击中占用点的飞镖的百分比。估计值是否可以接受?

你能保证所有形状都是圆形和矩形吗?您可能能够拼凑出适合他们的解决方案。如果Shapes可能会进一步扩展,那么这将不起作用。

答案 3 :(得分:1)

对于位置大小,应向下钻取以获得大小,因为形状可能是组,这会导致更高的计数

案例位置(x,y,形状)=>大小(形状)

即如果size是Shape

中的形状数

答案 4 :(得分:0)

案例g:组=> g.shape.map(size(_))。sum

案例组(ss @ *)=> ss.map(size())。sum

这两个都给出了误差值sum不是Seq [Int]的成员 然而,这个oen工作  case Group(shapes @ _ *)=> (0 /:形状){_ + size(_)