检查大于通用元组元素

时间:2013-03-06 14:25:28

标签: scala

我有一种方法可以将不同类型的元组添加到列表中,第一个元组元素始终是Int。我需要做一个“大于”比较但是在Any类型上不允许这样做。有人能告诉我如何在下面达到预期的效果吗?

由于 Des

private def add(list: List[Product], item: Product): List[Product] = {
  if(list.isEmpty || list.head.productElement(0) > item.productElement(0)) item :: list
  else add(list.tail, item)
}

2 个答案:

答案 0 :(得分:1)

如果由于Producer具有变量arity而无法接受ziggystar的建议,则可以通过重构避免复杂且可能不太可读的方法来实现预期效果。例如:

case class Item(i: Int, item: Product)

def add(list: List[Item], item: Item): List[Item] = {
  if (list.isEmpty || list.head.i > item.i) item :: list
  else add(list.tail, item)
}

,使用时,如下所示:

add(Nil, Item(1, (1, "b"))) // List(Item(1,(1,b)))
add(List(Item(1, (1, "a"))), Item(2, (1, "b"))) // List(Item(2,(1,b)))
add(List(Item(2, (1, "a"))), Item(1, (1, "b"))) // List(Item(1,(1,b)), Item(2,(1,a))

答案 1 :(得分:0)

如果你愿意采用反思,你可以使用名义和结构类型的混合:

import scala.language.reflectiveCalls

// A structural type exploiting the fact that all tuples have a _1 field
type IntComponent = { val _1: Int }

def add(list: List[Product with IntComponent], item: Product with IntComponent): List[Product with IntComponent] = {
  if(list.isEmpty || list.head._1 > item._1) item :: list
  else add(list.tail, item)
}

组合Product with IntComponent并非绝对必要,IntComponent就足够了。但是,这种组合可以让您更安全,并且如果需要,它允许您使用Product声明的字段和方法。

这为您提供了相当多的静态类型安全性:

add(Nil, (1, "foo", null)) // ok

add(Nil, ("foo", 0)) // error
  // error: type mismatch;
  //    found   : String("foo")
  //    required: Int

add(List[Product with IntComponent](Tuple1(1), Tuple2(-1, true)), (0, "yes"))
  // Explicit type annotation required, error otherwise
  //     found   : List[Product with Serializable]
  //     required: List[Product with this.IntComponent]

这种方法的明显弱点是,你可以潜入任何Product with IntComponent的物体,例如

case class FakeTupleA(_1: Int)

add(Nil, FakeTupleA(99)) // ok

如果没有Product要求,以下内容也适用:

add(Nil, new FakeTupleB(99))
  // error: type mismatch;
    // found   : this.FakeTupleB
    // required: Product with this.IntComponent