Scala фильтр на будущее логическое внутри для понимания - PullRequest
1 голос
/ 17 марта 2020

Я пытаюсь проверить будущее последовательности элементов. Мой метод validate также возвращает будущее логического значения. Я смог заставить его работать, но я не уверен, что сам понимаю, что здесь происходит.

Итак, у меня есть код, который работает, и тот, который не работает. У кого-нибудь есть идеи, что здесь происходит? Кроме того, как заставить это работать, соединяя фильтр после карты так, чтобы это все в одном месте и не использовало назначение позже?

def main(args: Array[String]): Unit = {
    println(Await.result(testMethod(), Duration.Inf))
}
def validationMethod(n: Int) = {
    Future { n % 2 == 0 }
}

Код, который работает:

def testMethod() = {
for {
  seqOfIntegers <- Future { List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) }
  numberToBooleanTupleSeq <- Future.sequence(seqOfIntegers.map {
    number =>
      validationMethod(number)
        .map(validtedBooleanTuple => (number, validtedBooleanTuple))
  })

  finalIntegerSeq = numberToBooleanTupleSeq.filter(_._2).map(_._1)
} yield {
  finalIntegerSeq
}

Код, который не работает:

  def testMethod() = {
    for {
      seqOfIntegers <- Future { List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) }
      finalIntegerSeq <- Future.sequence(seqOfIntegers.map {
        number =>
          validationMethod(number)
            .map(validtedBooleanTuple => (number, validtedBooleanTuple))
            .filter(_._2)
            .map(_._1)
      })
    } yield {
      finalIntegerSeq
    }
  }

1 Ответ

2 голосов
/ 17 марта 2020

Следуйте за типами.
В вашем втором фрагменте вы звоните filter через Future , что не работает, как вы ожидаете. Поскольку он не удаляет этот элемент из коллекции фьючерсов, а возвращает fail Future с NoSuchElementException, что затем приводит к сбою всего кода с таким исключением .

Кстати, вот отполированная версия вашего рабочего кода, которая немного более эффективна и удобочитаема.

import scala.concurrent.Future

def validationMethod(n: Int): Future[Boolean] =
  Future((n % 2) == 0)

def testMethod() =
  for {
    seqOfIntegers <- Future {
      List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    }

    validated <- Future.traverse(seqOfIntegers) { number =>
      validationMethod(number).map { boolean =>
        number -> boolean
      }
    } 

    result = validated.collect {
      case (n, true) => n
    }
  } yield result
...