Карта не добавляет запись в рекурсивную функцию - PullRequest
1 голос
/ 11 октября 2019

Я работаю со 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. Что я делаю не так и как это решить?

Онлайн-скрипка: https://scalafiddle.io/sf/eqSxPX9/0

Ответы [ 2 ]

2 голосов
/ 11 октября 2019

Существует простая ошибка, когда вы вызываете 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 голос
/ 11 октября 2019

Я вижу много проблем с вашим кодом, но отвечаю на ваш вопрос: каждый раз, когда вы звоните addAll, вы создаете индекс с пустой картой. В строке case ::(head, next) => addAll(next, add(head)) вы не используете индекс, полученный из списка параметров. Разве это не должно быть каким-то образом обновлено?

Остерегайтесь того, что реализация карты по умолчанию является неизменной, а обновление карты означает, что вам нужно создать новую с новым добавленным значением.

...