斯卡拉模式匹配困境

时间:2015-05-27 20:36:44

标签: scala design-patterns pattern-matching

我有以下程序,其中包含带模式匹配的递归函数。 此代码有效

def randomSelect(num:Int, lst:List[Symbol]):List[Symbol] = (num, lst) match{

     /** traveerse list recursively extracting randomelemnents

    * 

    */

  case (n, l) =>  {

      if (n>0) {
        println("At " + n + " we got:" + l)
        val rnd = getRandom(l.length)
        val item = l(rnd)
        lst(rnd) :: randomSelect(n - 1, l.filter(it => it != item))
      } else List[Symbol]()

  }

}

而以下情况并非如此。我无法理解为什么

def randomSelect(num:Int, lst:List[Symbol]):List[Symbol] = (num, lst) match{

     /** traveerse list recursively extracting randomelements

    * 

    */

  case (n, mylist) =>  {
         val rnd = getRandom(mylist.length)
         val item = mylist(rnd)
         lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item))

  }
  case (0, mylist) => List[Symbol]()

}

在第二个conde片段中,永远不会调用case(0,mylist)。

我错过了什么?

亲切的问候  马可

3 个答案:

答案 0 :(得分:1)

现在你有类似的东西:

if (the input is a Tuple2) {
   do something
} else if (the input is a Tuple2 with a 0 as the first item) {
   do other thing
}

case (n, mylist) =>匹配(0, List(...))您需要为第一个表达式添加一个保护或重新排序您的案例,以便首先达到0个案例。

所以:

case (0, mylist) => List[Symbol]()
case (n, mylist) =>  {
  val rnd = getRandom(mylist.length)
  val item = mylist(rnd)
  lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item))
}

case (n, mylist) if n > 0 =>  {
  val rnd = getRandom(mylist.length)
  val item = mylist(rnd)
  lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item))
}
case (0, mylist) => List[Symbol]()

答案 1 :(得分:0)

在以下语句中:case (n, mylist)n是一个绑定到该位置中任何值的变量,在您的情况下为num: Int。所以n绑定到所有整数值。当它恰好为0时,你的第一个案例就匹配它,因此永远不会达到第二个案例陈述。

有两种方法可以解决这个问题。第一:

case (n, mylist) if n > 0 =>  {
         val rnd = getRandom(mylist.length)
         val item = mylist(rnd)
         lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item))

  }
case _ => List.empty[Symbol]

我使用了通配符,因为您没有使用列表或n

第二种方式:

case (0, _) => List.empty[Symbol]
case (n, mylist) =>  {
         val rnd = getRandom(mylist.length)
         val item = mylist(rnd)
         lst(rnd) :: randomSelect(n - 1, mylist.filter(it => it != item))

  }

答案 2 :(得分:0)

如前所述,对案例进行重新排序,以便首先评估最具体的案例。

然而,两种情况的模式匹配可以简化为if-else表达式(不必通过警卫复制if-else),注意在这种递归方法中,基本(平凡)情况可能是首先宣布,主要是为了提高可读性,

def randomSelect(n:Int, l:List[Symbol]):List[Symbol] = {
  if (n <= 0) List[Symbol]()
  else {
      println("At " + n + " we got:" + l)
      val rnd = getRandom(l.length)
      val item = l(rnd)
      lst(rnd) :: randomSelect(n - 1, l.filter(it => it != item))
  }
}