Производительность для понимания в scala

У меня вопрос об эффективности for-comprehensions в scala.

Этот следующий код занимает около 45 секунд для запуска, когда perm является списком около 550 элементов

perm = some list
for{
   perm <- perms.withFilter(_.size > 0)
   wordList = somefunction(perm) //expensive operation, wordlist is a list of strings
   sentenceList = somefunction1(perm) //very expensive operation, sentenceList is a list of list of strings
   word <- wordList
   sentence <- sentenceList
} yield { word::sentence}

Когда я изменил следующий код на следующий, он запустил за 3 секунды с тем же списком Perm

perm = some list
for{
   perm <- perms.withFilter(_.size > 0)
   word <- somefunction(perm) //expensive operation
   sentence <- somefunction1(perm) //very expensive operation
} yield { word::sentence}

Разница в производительности имеет отношение к ленивой оценке в Scala?

Ответ 1

Пусть обезвреживают оба понятия:

1).

perms.withFilter(_.size > 0).flatMap { perm =>
  val wordList = somefunction(perm) //expensive operation
  val sentenceList = somefunction1(perm) //very expensive operation
  wordList.flatMap { word =>
    sentenceList.map { sentence =>
      word::sentence
    }
  }
}

2.)

perms.withFilter(_.size > 0).flatMap { perm =>
  somefunction(perm).flatMap { word =>
    somefunction1(perm).map { sentence =>
      word :: sentence
    }
  }
}

В первом случае обе дорогие функции будут выполняться каждый раз. Во втором случае, когда somefunction(perm) возвращает пустой результат, somefunction1(perm) никогда не будет выполнен.

Ответ 2

В вашем первом фрагменте, кажется, вы "зацикливаетесь" на каждом элементе, который у вас есть в вашей переменной, с каждым элементом в списке слов; По сути, декартово произведение.

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

Кажется, я не могу разобрать все типы переменных, поэтому его довольно сложно полностью объяснить.