当 get 保证成功时 Option.get 更好的替代品
Nicer alternatives to Option.get when get is guaranteed to succeed
添加 Scalaz Maybe 的原因之一是 get rid of get:
Some differences from std lib Option:
- No unsafe get method
我知道 get
可能不安全,但有时是安全的(在 Option
不为空之前验证过的代码中)。在某些情况下,人们可以很容易地避免使用 get
,但有时对我来说并不是那么明显。以下代码中 get
的替代方案是什么?
def point(cursor:Int) : Option[XY]
def paste(cs: Seq[Int]) = {
if (validateSelection(cs)) {
cs.size match {
case 2 => // between two points
// editablePoint returning Option for general case,
// but here it is known to succeed as validateSelection passed
val beDiff = point(cs.head).get.xy - point(cs.last).get.xy
...
case _ =>
...
}
...
}
要摆脱准安全 get
,您必须重构您的 validateSection
。在您的示例中,它可能 returns a Boolean
:
def validateSection(cs: Seq[Int]): Boolean
然而,您可以return 证据,cs
是有效的:
/* Returns the first and last values of the sequence,
* if the sequence's length == 2. Otherwise `Empty`.
*/
def validateSection(cs: Seq[Int]): Maybe[(Int, Int)]
然后您可以将代码段重构为:
def paste(cs: Seq[Int]) = {
match validateSelection(cs) {
case (first, last) =>
val beDiff = first - last
...
case _ =>
...
}
...
}
编辑 你可以进一步理解这个想法:创建辅助类型来摆脱函数的偏向性。
point
returns Option[XY]
,即它是部分的。我们应该尽量使输入参数更精确,所以point
可以是总的,即returnXY
。在不知道精确规格的情况下,我只能草拟解决方案:
case class Selection(/* ... */)
/* Constructed from `Selection` */
case class Cursor()
object Selection {
def first: Cursor = ???
def last: Cursor = ???
}
/* If `cs` is valid, we return a `ValidSelection`, othersise `Empty`. */
def validateSelection(cs: Seq[Int]): Maybe[Selection]
/* With more precise type, we can have total `point`. */
def point(cursor: Cursor): XY
这种方法起初可能看起来很老套,但在这里我们利用了拥有类型系统的优势。避免 stringly typed 或 列表类型 编程。
添加 Scalaz Maybe 的原因之一是 get rid of get:
Some differences from std lib Option:
- No unsafe get method
我知道 get
可能不安全,但有时是安全的(在 Option
不为空之前验证过的代码中)。在某些情况下,人们可以很容易地避免使用 get
,但有时对我来说并不是那么明显。以下代码中 get
的替代方案是什么?
def point(cursor:Int) : Option[XY]
def paste(cs: Seq[Int]) = {
if (validateSelection(cs)) {
cs.size match {
case 2 => // between two points
// editablePoint returning Option for general case,
// but here it is known to succeed as validateSelection passed
val beDiff = point(cs.head).get.xy - point(cs.last).get.xy
...
case _ =>
...
}
...
}
要摆脱准安全 get
,您必须重构您的 validateSection
。在您的示例中,它可能 returns a Boolean
:
def validateSection(cs: Seq[Int]): Boolean
然而,您可以return 证据,cs
是有效的:
/* Returns the first and last values of the sequence,
* if the sequence's length == 2. Otherwise `Empty`.
*/
def validateSection(cs: Seq[Int]): Maybe[(Int, Int)]
然后您可以将代码段重构为:
def paste(cs: Seq[Int]) = {
match validateSelection(cs) {
case (first, last) =>
val beDiff = first - last
...
case _ =>
...
}
...
}
编辑 你可以进一步理解这个想法:创建辅助类型来摆脱函数的偏向性。
point
returns Option[XY]
,即它是部分的。我们应该尽量使输入参数更精确,所以point
可以是总的,即returnXY
。在不知道精确规格的情况下,我只能草拟解决方案:
case class Selection(/* ... */)
/* Constructed from `Selection` */
case class Cursor()
object Selection {
def first: Cursor = ???
def last: Cursor = ???
}
/* If `cs` is valid, we return a `ValidSelection`, othersise `Empty`. */
def validateSelection(cs: Seq[Int]): Maybe[Selection]
/* With more precise type, we can have total `point`. */
def point(cursor: Cursor): XY
这种方法起初可能看起来很老套,但在这里我们利用了拥有类型系统的优势。避免 stringly typed 或 列表类型 编程。