我目前正在从事函数式编程-对此我还很陌生。我在这里正确使用选项吗?我目前对自己的技能没有把握。 我希望我的代码尽可能安全-有人可以指出我在这里做错了吗,或者还不错吗?我的代码非常简单:
def main(args: Array[String]): Unit =
{
val file = "myFile.txt"
val myGame = Game(file) //I have my game that returns an Option here
if(myGame.isDefined) //Check if I indeed past a .txt file
{
val solutions = myGame.get.getAllSolutions() //This returns options as well
if(solutions.isDefined) //Is it possible to solve the puzzle(crossword)
{
for(i <- solutions.get){ //print all solutions to the crossword
i.solvedCrossword foreach println
}
}
}
}
-谢谢! ^^
答案 0 :(得分:4)
使用高阶函数代替Java样式的for循环:
myGame match {
case Some(allSolutions) =>
val solutions = allSolutions.getAllSolutions
solutions.foreach(_.solvedCrossword.foreach(println))
case None =>
}
答案 1 :(得分:2)
根据经验,您可以将Option
视为Java空指针的替代品。也就是说,在Java中可能要使用null
的情况下,在Scala中使用Option
通常是有意义的。
您的Game()
函数使用None
表示错误。因此,您并没有真正将其用作null
的替代品(至少我认为等效的Java方法在那里返回null
而不是抛出异常是一种不好的做法),而是替换例外。这不是Option
的好用法,因为它会丢失错误信息:您无法再区分文件不存在,文件格式错误还是其他类型的错误。
您应该使用Either
。 Either
由情况Left
和Right
组成,其中Right
类似于Option
的{{1}},但Some
与{ {1}},因为它也接受一个参数。在这里,该参数可用于存储有关错误的信息。因此,您可以创建一个包含可能的错误类型的案例类,并将其用作Left
的参数。或者,如果您永远不需要以其他方式处理错误,而只是将错误呈现给用户,则可以使用带有错误消息的字符串作为None
的参数,而不是大小写类。
在Left
中,您只是使用Left
代替空白列表。这是不必要的,因为空白列表不需要替换。没有解决方案时,只返回一个空列表是完全可以的。
在与getAllSolutions
进行交互时,您使用的是None
+ Option
,这有点反作用。如果您知道自己从未拥有过的选项isDefined
,可以将get
用作快捷方式,但通常应避免使用。 get
通常仅应在需要知道某个选项是否包含值但不需要知道该值的情况下使用。
在需要同时知道是否有一个值和该值是什么的情况下,应使用模式匹配或None
的高阶函数之一,例如isDefined
,Option
,map
(如果您斜视一下并将别名参数视为类似函数,则这是一种高阶函数)。如果您想对有一个值的值做某事,否则不做任何事,则可以使用flatMap
(或等效地getOrElse
循环),但请注意,您实际上不应做任何事在这里的错误情况。您应该改为将错误告知用户。
答案 2 :(得分:1)
如果您只需要打印出来,以防万一,那么您可以使用理解力强的Scala方式
for {
myGame <- Game("mFile.txt")
solutions <- myGame.getAllSolutions()
solution <- solutions
crossword <- solution.solvedCrossword
} println(crossword)