【问题标题】:Scala - return a Boolean that is neither True or FalseScala - 返回一个既不是 True 也不是 False 的布尔值
【发布时间】:2017-09-29 06:20:13
【问题描述】:

我已经阅读了为什么不鼓励在 Scala 中使用“null”。但是我遇到了一个方法,我想返回一个在某些条件下既不是真也不是假的“空”布尔值。

def exampleMethod (query: String): Boolean =
{  
  var result: Boolean = false
  try
  { 
     //This will take the input query and return "true" or "false" 
     //depending on the state of the database
     result = boolQueryResult.evaluate()
     return result
  }
  catch
  {
     case e: Throwable => logger.info(e.toString)
  }
  logger.info("Something is wrong! I want to return a boolean with nothing in it!")
  return result
  }

在上面的代码中,我使用了 evaluate() 方法,该方法将返回 true 或 false,然后该值将以布尔值返回。但是如果出现问题并且执行了 catch 块,我想返回一个非真或假的布尔值,以表明输入字符串存在错误。在此方法的当前版本中,布尔值被初始化为“false”,这并不理想,因为它表明 evaluate() 返回了 false,而不是执行了 catch 块。有没有办法初始化这个变量,如果抛出异常,它不会返回“true”或“false”?

【问题讨论】:

    标签: scala


    【解决方案1】:

    @bipll 是对的。 Option[Boolean] 是 Scala 做你想做的事的方式。这就是它的完成方式。

    def exampleMethod(query: String): Option[Boolean] =
      try {
        Some(boolQueryResult.evaluate())
      } catch {
          case e: Throwable => logger.info(e.toString)
                               None
      }
    

    【讨论】:

    • 我很喜欢这些答案,但这是我最终使用的解决方案。我喜欢它的简单性,尽管我希望有一种方法可以在 Scala 中使用一个简单的布尔项来实现这一点。我相信在 Java 中你可以简单地设置一个 Boolean == null。
    • Scala 是一种类型的语言。由于null 不是布尔值,因此不允许。许多人认为 Java 的松散类型和不断的空值检查是一个缺陷。如果某些东西可能不存在,那么它将通过Option[Boolean]Option[Int]Option[String] 等成为类型系统的一部分。这样接收代码就不会忘记检查空值,因为访问Boolean 是不同于访问Option[Boolean]
    【解决方案2】:

    虽然其他答案建议使用Option(返回Some(true)Some(false)None,但在返回None 的情况下会丢失错误消息。因此,我建议而是使用 TryEither

    一个示例可能如下所示:

    import scala.util.{Either, Left, Right}
    import scala.util.{Failure, Success, Try}
    // Notice the return type: we either return the error as a Left(...), or a Right(boolean result)
    def exampleMethod (query: String): Either[Throwable, Boolean] = {
      // Is this where you meant to use `query`? It's not used in your original post
      Try(boolQueryResult.evaluate(query)) match {
        case Success(result) => Right(result)
        case Failure(exception) => Left(exception)
      }
    }
    

    这样,方法的调用者可以决定要做什么。例如,您可以对该方法的结果进行模式匹配,并在记录错误时将Left(exception) 转换为None

    val queryResult: Option[Boolean] = exampleMethod("bad_query") match {
      case Right(result) => Some(result)
      case Left(exception) => {
        Logger.warn(s"There was an issue with exampleMethod: ${exception.getMessage}", exception)
        None
      }
    }
    

    【讨论】:

      【解决方案3】:

      【讨论】:

        【解决方案4】:

        这是Try 类型的一个很好的例子

        def exampleMethod (query: String): Try[Boolean] =
        {  
          Try
          { 
             //If this throws an exception, it will be caught within the Try as a Failure
            // and can be handled later, otherwise the result is stored in a Success
             boolQueryResult.evaluate()
          }
        }
        

        Try 可以包装一个可能失败的表达式。它将包含 Success 中的值,如果抛出异常,则 Try 将包含该异常而不是 Failure。然后,您可以使用mapflatmapforeach 等方法对值进行操作。更好的是修改您的评估方法以返回 Try 或其他适当的类型,而不是抛出异常,但这并不总是可能的。

        return 是不必要的,不推荐在 Scala 中使用。方法中最后一个表达式的结果会自动返回

        另一种选择是根本不使用BooleanBoolean 的问题在于它只能保持两种状态,而您需要三种状态。您可以创建一个具有三种状态的新 ADT,而不是使用包装器。

        sealed trait ExampleResult
        case object TrueResult extends ExampleResult 
        case object FalseResult extends ExampleResult 
        case object QueryError extends ExampleResult 
        

        因为 Trait 是密封的,只有同一个文件中的类可以扩展 trait ExampleResult,所以你知道它总是这三个选项之一。

        然后您可以像这样编写代码

        def exampleMethod (query: String): ExampleResult =
        {  
          try
          { 
             //This will take the input query and return "true" or "false" 
             //depending on the state of the database
        
             if(boolQueryResult.evaluate()){
               return TrueResult
             } else {
               return FalseResult
             }
          }
          catch
          {
             case e: Throwable => logger.info(e.toString)
          }
          logger.info("Something is wrong! I want to return a boolean with nothing in it!")
          return QueryError
          }
        

        【讨论】:

        • 一个好的 scala 方法不应该返回 TryException in Try 就像 Object:你不知道如何处理它。如果您知道该方法可能会出现什么样的错误,请使用Either。如果不是 - 只需传播错误并在调用者代码中处理它。
        • 这是相当固执的观点,当然也不是 Scala 社区普遍认同的观点。
        猜你喜欢
        • 2013-11-14
        • 1970-01-01
        • 2021-02-14
        • 2020-03-15
        • 2021-09-24
        • 2017-11-23
        • 1970-01-01
        • 2019-03-24
        相关资源
        最近更新 更多