将 Either 取消引用回到对象中

De-referencing Either back into the object

我正在尝试使用函数中的 Either return 类型来取回对象或字符串。如果它是一个对象,我想从这个对象开始调用方法。如果它是一个字符串,我想在别处调用一些其他函数。我总是被挂断,因为被 returned 的东西不是我正在 returning 的对象,它是 "left" 类型的,我似乎无法从中取出那个对象"Left" 类型变回我想要的 "Player" 类型。这包含在扩展可变队列的对象中。这是我的函数,它根据 ActionQueue 对象中的键在 Map 中查找 Player 对象:

def popCurrentAction : Either[Player, String] = {
  val currentAction = this.dequeue
  this.enqueue(currentAction)

  if (playerMap.get(currentAction) != None) {
    Left((playerMap.get(currentAction).get))
  }
  else {
    Right(currentAction)
  }
}

这是我的函数,它试图使用 returns "Player" 对象或字符串的函数。

def doMove = {
  var currentAction = ActionQueue.popCurrentAction
  if (currentAction.isLeft) {
    var currentPlayer = currentAction.left
    var playerDecision = currentPlayer.solicitDecision() // This doesn't work

    println(playerDecision)

  }
  else {
    // Do the stuff if what's returned is a string.
  }
}

我试过使用 .fold 函数,它允许我调用 solicitDecision 函数并得到它 return 的内容,但我想直接使用 Player 对象。当然这是可能的。有人可以帮忙吗?

  var currentPlayer = currentAction
  var playerDecision = currentPlayer.fold(_.solicitDecision(), _.toString())
  // This is close but doesn't give me the object I'm trying to get!
  println(playerDecision)

你没有说明你遇到了什么错误,只是 "this doesn't work",而且你发布的代码不够完整,无法编译和测试。当编译器失败时 currentPlayer 类型是什么?

话虽如此,您可能会考虑重构您的代码。

def doMove = ActionQueue.popCurrentAction.fold(getDecision, stringStuff)

def getDecision(player: Player) = ....
def stringStuff(str: String) = ....

同时区分大小写和提取内容的最佳方法是使用模式匹配。

在您的情况下,大致是以下代码:

def doMove = {
  val currentAction = ActionQueue.popCurrentAction
  currentAction match {
    case Left(currentPlayer) => 
      val playerDecision = currentPlayer.solicitDecision()
      println(playerDecision)
    case Right(string) =>
      println(string)
  }
}

另请注意,我使用 val 而不是 var。当你有一个你不打算改变的变量时,val 是更好的风格(粗略地说,它使一个只读变量)。