Scala Future gibt None zurück

Hi,
ich möchte für ein Spiel alle möglichen Züge für den Computer generieren. Ich teile die Berechnung in zwei Teile auf. Future1 kümmert sich um die eine Spielhälfte, Future2 um die andere.
Um das Ergebnis zurückgeben zu können, muss ich auf die beiden Futures warten. Unglücklicherweise ist das Ergebnis (siehe Variable value) None und der Debbuger springt zu case_ , obowohl die Variable futureFullMoveList Elemente enthält.

Jemand eine Idee woran das liegen könnte?

Danke im Voraus!

  def generatePossibleMoves(controller: Connect4GameController, gameField: Connect4GameField, player: Player): List[Move] = {

    def possibleMove(colFrom: Int, colTo: Int,  moveList: List[Move]): List[Move] = {
      if (colFrom < colTo)
        if (verticalMoveIsPossible(gameField, colFrom))
          possibleMove(colFrom + 1, colTo, moveList :+ new Connect4Move(controller, colFrom))
        else
          possibleMove(colFrom + 1, colTo, moveList)
      else
        moveList
    }

    val futureMoveList1 = Future {
      val to =  Connect4GameField.FIELD_COLUMNS / 2
      possibleMove(0, to, Nil)
    }

    val futureMoveList2 = Future {
      val from =  (Connect4GameField.FIELD_COLUMNS / 2)
      possibleMove(from, Connect4GameField.FIELD_COLUMNS, Nil)
    }

    val futureFullMoveList = futureMoveList1 map { moveList1 =>
      futureMoveList2 map { moveList2 =>
        moveList1 ++ moveList2
      }
    }

    val value = Await.result(futureFullMoveList, 10 seconds).value
    value match {
      case Some(bla) =>  return bla.get
      case _ => return Nil
    }
  }

Ich benutze nun folgenden Code und er funktioniert nun, weshalb auch immer. :stuck_out_tongue:


val futureMoveList1 = Future {
      val to =  Connect4GameField.FIELD_COLUMNS / 2
      possibleMove(0, to, Nil)
    }

    val futureMoveList2 = Future {
      val from =  (Connect4GameField.FIELD_COLUMNS / 2)
      possibleMove(from, Connect4GameField.FIELD_COLUMNS, Nil)
    }

    val futureFullMoveList = Future.sequence(Seq(futureMoveList1, futureMoveList2))

    val fullMoveList = Await.result(futureFullMoveList, 10 seconds)

    return fullMoveList.toList.flatten

Vielleicht kann @Landei auch erklären, wieso :wink:

If the computation of one Future depends on the result of another, you’ll likely want to resort to flatMap to avoid a deeply nested structure of futures.

The Neophyte’s Guide to Scala Part 8: Welcome to the Future - Daniel Westheide

Genau das scheint hier das Problem zu sein:


val futureFullMoveList = futureMoveList1 map { moveList1 =>
      futureMoveList2 map { moveList2 =>
        moveList1 ++ moveList2
      }
    }

Das “innere” map liefert ein Future[List[Move]], das äußere also ein Future[Future[List[Move]]].

Versuche mal


val futureFullMoveList = futureMoveList1 flatMap { moveList1 =>
      futureMoveList2 map { moveList2 =>
        moveList1 ++ moveList2
      }
    }

(alle Angaben ohne Gewähr, hab’s nicht probiert)