递归处理scala

时间:2016-09-06 01:15:55

标签: scala recursion functional-programming lisp tail-recursion

我正在教自己scala并试图增加我的FP技能。

我的一个参考资料,编程语言要点(available here),有一个简单的递归函数列表。在页面27/50,我们被要求实现swapper()函数。

(swapper s1 s2 slist) returns a list the same as slist, but
with all occurrences of s1 replaced by s2 and all occurrences of s2 replaced by s1.


> (swapper ’a ’d ’(a b c d))
(d b c a)
> (swapper ’a ’d ’(a d () c d))
(d a () c a)
> (swapper ’x ’y ’((x) y (z (x))))
((y) x (z (y)))

在scala中,这是:

swapper("a", "d", List("a","b","c","d"))
swapper("a", "d", List("a","d",List(),"c","d"))
swapper("x", "y", List( List("x"), "y", List("z", List("x"))))

我的scala版本处理所有版本保存最终x。

def swapper(a: Any, b: Any, lst: List[Any]): List[Any] ={
   def r(subList :List[Any], acc : List[Any]): List[Any] ={
     def swap (x :Any, xs: List[Any]) =
       if(x == a){
         r(xs, acc :+ b)
       } else if (x == b) {
         r(xs, acc :+ a)
       } else {
         r(xs, acc :+ x)
       }
     subList match {
     case Nil =>
       acc
     case List(x) :: xs =>
       r(xs, r(List(x), List()) +: acc)
     case x :: xs =>
       swap(x,xs)
     //case List(x) :: xs =>
   }
   }
  r(lst, List())
}

本能地,我认为这是因为我没有交换“case List(x):: xs”部分,但我仍然在努力修复它。

更难的是,这种情况打破了尾部调用优化。我该怎么做?我可以在哪里了解更多有关一般解决方案的信息?

3 个答案:

答案 0 :(得分:2)

您可以将此foldRight与模式匹配方法一起使用:

def swapper(a:Any, b:Any, list:List[Any]):List[Any] = 
  list.foldRight(List.empty[Any]) {
    case (item, acc) if item==a => b::acc
    case (item, acc) if item==b => a::acc
    case (item:List[Any], acc) => swapper(a, b, item)::acc
    case (item, acc) => item::acc
  }     

甚至更简单(感谢@marcospereira):

def swapper(a:Any, b:Any, list:List[Any]):List[Any] = 
  list.map {
    case item if item==a => b
    case item if item==b => a
    case item:List[Any] => swapper(a, b, item)
    case item => item
  }  

答案 1 :(得分:1)

解决此问题的更简单方法就是使用map

def swapper[T](a: T, b: T, list: List[T]): List[T] = list.map { item =>
  if (item == a) b
  else if (item == b) a
  else item
}

答案 2 :(得分:1)

这似乎有效。

def swapper[T](a: T, b: T, lst: List[_]): List[_] = {
  val m = Map[T, T](a -> b, b -> a).withDefault(identity)
  def swap(arg: List[_]): List[_] = arg.map{
    case l: List[_] => swap(l)
    case x: T => m(x)
  }
  swap(lst)
}

List元素不一致,因为它可能是一个元素,或者它可能是另一个List,因此类型为List[Any],这是一个确定的叹息,有人需要重新考虑这个数据表示。