【问题标题】:How to deal with defaults idiomatically in Scala?如何在 Scala 中惯用地处理默认值?
【发布时间】:2014-04-25 19:53:21
【问题描述】:

假设我有以下功能

def getHost():Option[String] = ... def getPort():Option[Int] = ...

现在,如果这些函数返回 None,我想使用默认值。

def makeURL() = { val host = getHost() getOrElse "localhost" val 端口 = getPort() getOrElse 8080 java.net.URL("http", 主机, 端口, "myPath") }

不幸的是,这段代码在 Scala 中看起来并不惯用。我希望makeURL 更像一个函数组合。你会如何改变makeURL

【问题讨论】:

  • 在我看来很地道。

标签: scala


【解决方案1】:

我不会改变它。没关系。这种语法的好处是它简洁

当然,您可以使用这样的纯大型功能方法来更改它:

val host = getHost match {
  case Some(h) => h
  case None => "localhost"
}

但是你会得到四行代码,而不是一行。

【讨论】:

  • 谢谢,但我想我无法更改函数 getHostgetPort
  • 但你甚至不需要
  • 根据您的 Scala 版本,无论如何这将分解为 getOrElse,实际上我更喜欢 getOrElse 的可读性而不是这里的案例......所以,我不会甚至改变任何东西
【解决方案2】:

我同意@serejja 的观点,你写的很好。但是,如果您觉得必须返回带有预设默认值的 Option

 trait WithDefaults extends SomeBase{
   def defaultUrl = "localhost"

   abstract def makeURL() = withDefault(defaultUrl){ 
     super makeURL() 
   }

   protected def withDefault[A](default: A)(f: => Option[A]) = f match{
     case Some(v) => Some(v)
     case None => Some(default)
   }
 }

在上面堆上一个trait,然后你的界面永远不必改变,你的所有代码都将“正常工作”,而忽略了可能存在默认值的事实。话又说回来,这也会让你问为什么它首先是Option...

【讨论】:

    【解决方案3】:

    使用getOrElse 已经是惯用的了,因为你是在推动功能而不是拉动它:而不是问'你是None吗?如果然后执行此操作,否则执行此操作”,您的意思是“我希望完成此操作,如果您没有足够的信息,请使用此默认设置”。
    如果您愿意使用一些scalaz,使用| 运算符看起来会更好一些:

     import scalaz._
     import Scalaz._
    
    
     def makeURL() = {
      val host = getHost() | "localhost"
      val port = getPort() | 8080
      java.net.URL("http", host, port, "myPath")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 2021-07-01
      相关资源
      最近更新 更多