我正在与scala一起使用,并希望创建一个具有函数的类,该函数将递归地添加到地图中。
class Index(val map: Map[String, String]) {
def add(e: (String, String)): Index = {
Index(map + (e._1 -> e._2))
}
def addAll(list: List[(String, String)], index: Index = Index()): Index = {
list match {
case ::(head, next) => addAll(next, add(head))
case Nil => index
}
}
}
object Index {
def apply(map: Map[String, String] = Map()) = {
new Index(map)
}
}
val index = Index()
val list = List(
("e1", "f1"),
("e2", "f2"),
("e3", "f3"),
)
val newIndex = index.addAll(list)
println(newIndex.map.size.toString())
由于该函数应该在地图上添加3个条目,所以我将这段代码打印为3,但实际输出为1。我做错了什么以及如何解决?
答案 0 :(得分:2)
在调用add(head)
的地方应该发生index.add(head)
,这是一个简单的错误。
但是,在编写这样的递归例程时,最好使用嵌套方法,例如:
def addAll(list: List[(String, String)]): Index = {
@annotation.tailrec
def loop(rem: List[(String, String)], index: Index): Index = {
rem match {
case head :: tail => loop(tail, index.add(head))
case Nil => index
}
}
loop(list, Index())
}
这使函数可以进行尾部递归并由编译器进行优化,并且还避免了addAll
方法的虚假参数。
答案 1 :(得分:1)
我看到您的代码有很多问题,但需要回答您的问题:
每次调用addAll
时,都会创建一个带有空Map的索引。
在case ::(head, next) => addAll(next, add(head))
行中,您没有使用从参数列表中获得的索引。那不应该以某种方式更新吗?
请注意,默认地图实现是不可变的,更新地图意味着您需要使用添加的新值创建一个新地图。