How to perform pattern matching with vararg case classes?

孤者浪人 提交于 2019-12-04 00:24:25

Either of these will work, the second is probably preferred if a little weird at first glance. See 8.1.9 Pattern Sequences from the Scala Reference.

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

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

This is using Scala 2.8. sum may not work on older versions.

The syntax for vararg pattern matching is somewhat 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(_) }
}

Note that in the last line, you sum up the sizes of all sub-shapes starting with zero using the /:-notation for folds.


How folds work: Folds accumulate the elements of a sequence using a given function.

So in order to compute the sum of a list, we would write (Haskell-style)

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

which would combine all elements of the list with the given addition function starting with 0 (and therefore compute the sum).

In Scala, we can write it this way:

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

which can be simplified to

(0 /: list) { _ + _ }

The first step is figuring out what you mean. The two most obvious choices are the total area covered by all the shapes, and the minimum rectangle containing them all. If for circles you return the actual area, they you probably have to go with the actual area.

There's no closed-form way to answer this. I might consider throwing a thousand random darts at a minimum enclosing rectangle and estimating the area as the percentage of darts that hit an occupied point. Is an estimate an acceptable response?

Are you guaranteed that all the shapes will be circles and rectangles? You might be able to cobble together a solution that would work for them. If Shapes might be extended further, then that won't work.

For Location size should drill down to get size since shape could be group which causes a higher count

case Location(x,y,shape) => size(shape)

That is if size is the number of shapes in the Shape

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

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

both of these gives the error value sum is not a member of Seq[Int]
However this oen works
case Group(shapes @ _*) => (0 /: shapes) { _ + size(_)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!