Lucas S.
Lucas S.

Reputation: 332

Map doesn't add entry in recursive function

I'm working with scala and want to make a class with a function which add recursively something to a map.

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())

I excepted this code to print 3, since the function is supposed to add 3 entries to the map, but the actual output is 1. What I'm doing wrong and how to solve it?

Online fiddle: https://scalafiddle.io/sf/eqSxPX9/0

Upvotes: 1

Views: 137

Answers (2)

Tim
Tim

Reputation: 27421

There is a simple error where you are calling add(head) where it should be index.add(head).

However it is better to use a nested method when writing recursive routines like this, for example:

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())
}

This allows the function to be tail recursive and optimised by the compiler, and also avoids a spurious argument to the addAll method.

Upvotes: 2

fusion
fusion

Reputation: 1287

I see many problems with your code but to answer your question: Each time you call addAll you create an Index with an empty Map. In the line case ::(head, next) => addAll(next, add(head)) you are not using the index that you get from the parameter list. Shouldn't that be somehow updated?

Beware that the default map implementation is immutable and to updating a map means that you need to create a new one with the new value added.

Upvotes: 1

Related Questions