Scala';实施方案的选择
在Scala中是如何实现的:Scala';实施方案的选择,scala,Scala,在Scala中是如何实现的: sealed trait Option[+A] { def get: A def isEmpty: Boolean def map[B](f: A => B): Option[B] = if (isEmpty) None else Some(f(this.get)) } object None extends Option[Nothing] { def isEmpty = true def get
sealed trait Option[+A] {
def get: A
def isEmpty: Boolean
def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
}
object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}
case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
在OOP世界中,我将如何假设:
sealed trait Option[+A] {
def map[B](f: A => B): Option[B]
}
object None extends Option[Nothing] {
def map[B](f: Nothing => B): Option[B] = this
}
case class Some[+A](get: A) extends Option[A] {
def map[B](f: A => B): Option[B] = Some(f(get))
}
后者有什么问题
是否在选项[A]
中使用匹配
,这是第三种方法(看起来像Haskell,但为什么?)
更新:我提到的第三种方式:
sealed trait Option[+A] {
def map[B](f: A => B): Option[B] = this match {
case None => None
case Some(a) => Some(f(a))
}
}
object None extends Option[Nothing] {
}
case class Some[+A](get: A) extends Option[A] {
}
我不确定您是否打算这样做,但您遗漏了
isEmpty
和get
的声明,任何人都需要这些声明来检查任意选项的内容,而无需向下转换到部分。由于这两种方法都需要由两个子类来定义,并且可以根据它们来定义map
,因此我认为最好在一个地方定义map
,利用其他方法的子类实现,与其在三个地方定义map
。我想,由于scala同时支持函数式和命令式以及面向it的java程序,这是让它们更容易填充的东西之一。
来自java程序员
val opt: Option[String] = ???
if (!opt.isEmpty) {
//do something with opt.get
} else {
//do some default...
}
可能比功能性方式更容易理解(即使使用getOrElse)
@Victor Moroz在其中一篇评论中写道,使用模式匹配代替此匹配{None=>default\u val;Some(v)=>v}
这不仅让刚接触函数世界的程序员更难理解,而且成本更高,因为选项的用途更多,instanceOf的成本也比简单的if高。这是表达式问题的一个方面,在这种情况下,我个人会选择match
,因为:a.)您不会有任何其他这种特性的实现(既因为这是该数据类型背后的逻辑,也因为下面的第二点);当您无法预先预测所有实现时,子类型多态性非常有用。b、 )它是密封的,因此您将获得详尽的模式匹配警告/错误。Scala实现可能使用标志表示速度,bool标志检查速度快且没有间接性。您可能还对scalaz的Maybe
实现感兴趣:相应的讨论:isEmpty
将在Scala中定义,如果我需要它,只要我停留在函数范式中,我就不这么做。对于get
也是一样,对于None
,我真的需要get
?我会使用getOrElse
或orElse
。您可以使用模式匹配检查选项的内容。我认为这应该是Scala的首选方式。scalaz开发人员甚至为选项
构建了一个名为Maybe
的替代品,而不使用不安全的get
。对于将选项视为零或一个元素的集合的用例,需要isEmpty。需要模式匹配的问题是,您将使隐式instanceof和cast成为必需的。对于可以用一个if
表达式处理的东西来说,它也要详细得多。if(isEmpty)default\u val else获取
vs此匹配{None=>default\u val;Some(v)=>v}
。在前一种情况下,最多有2个多态调用(isEmpty
,get
),后者可能在幕后使用instanceOf
,但只使用一次。我想演员是免费的。当然,在现实生活中,它会短得多x getOrElse default\u val
如果你想争论设计应该改变,你必须和Martin Odersky谈谈,但我认为你不会走得太远。我只是在解释我认为的原因。instanceOf
比多态调用成本更高isEmpty
?哪怕是其中的两个(包括get
)?我怀疑,他们应该是平等的。虽然同意Java的论点,但我猜Java程序员不会使用选项
,他们有null
和NullPointerException
。也许我的问题是错误的,不是Scala为什么这样做,而是应该如何做,我应该遵循Scala的路径,还是其他两个路径之一。