- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Scala 中,我逐渐失去了 Java/C 以面向控制流的方式思考的习惯,并习惯于先获取我感兴趣的对象,然后通常应用类似 match
的东西。或 map()
或 foreach()
用于收藏。我非常喜欢它,因为它现在感觉像是一种更自然、更直接的方式来构建我的代码。
渐渐地,我希望我能以同样的方式为条件编程;即先获取 bool 值,然后match
它做各种事情。一个成熟的match
但是,对于这项任务来说似乎有点矫枉过正。
比较:
obj.isSomethingValid match {
case true => doX
case false => doY
}
if (obj.isSomethingValid)
doX
else
doY
ifTrue:
和
ifFalse:
消息(及其变体)。是否有可能在 Scala 中编写这样的东西?
obj.isSomethingValid ifTrue doX else doY
val v = obj.isSomethingValid ifTrue someVal else someOtherVal
// with side effects
obj.isSomethingValid ifFalse {
numInvalid += 1
println("not valid")
}
Option
?我知道使用
Option
的更惯用方式就是把它当成一个集合,调用
filter()
,
map()
,
exists()
就可以了,但通常,最后,我发现我想执行一些
doX
如果它被定义,还有一些
doY
如果不是。就像是:
val ok = resultOpt ifSome { result =>
println("Obtained: " + result)
updateUIWith(result) // returns Boolean
} else {
numInvalid += 1
println("missing end result")
false
}
match
更好。 .
最佳答案
第一:我们可能无法重用 else
, 因为它是一个关键字,并且使用反引号来强制它被视为一个标识符是相当难看的,所以我将使用 otherwise
反而。
这是一个实现尝试。首先,使用 pimp-my-library 模式添加 ifTrue
和 ifFalse
至Boolean
.它们在返回类型 R
上进行了参数化并接受单个按名称参数,如果实现指定条件,则应评估该参数。但在这样做时,我们必须允许 otherwise
称呼。所以我们返回一个名为 Otherwise0
的新对象。 (为什么后面会解释为什么是 0),它将可能的中间结果存储为 Option[R]
.如果当前条件( ifTrue
或 ifFalse
)实现则定义,否则为空。
class BooleanWrapper(b: Boolean) {
def ifTrue[R](f: => R) = new Otherwise0[R](if (b) Some(f) else None)
def ifFalse[R](f: => R) = new Otherwise0[R](if (b) None else Some(f))
}
implicit def extendBoolean(b: Boolean): BooleanWrapper = new BooleanWrapper(b)
someTest ifTrue {
println("OK")
}
otherwise
子句,它不能返回
R
类型的值, 当然。所以这里是
Otherwise0
的定义:
class Otherwise0[R](intermediateResult: Option[R]) {
def otherwise[S >: R](f: => S) = intermediateResult.getOrElse(f)
def apply[S >: R](f: => S) = otherwise(f)
}
ifTrue
获得的中间结果时,它才会评估其传递的命名参数。或
ifFalse
是未定义的,这正是我们想要的。类型参数化
[S >: R]
具有
S
的效果被推断为命名参数的实际类型的最具体的常见父类(super class)型,例如,
r
在这个片段中有一个推断类型
Fruit
:
class Fruit
class Apple extends Fruit
class Orange extends Fruit
val r = someTest ifTrue {
new Apple
} otherwise {
new Orange
}
apply()
别名甚至允许您跳过
otherwise
短代码块的方法名称:
someTest.ifTrue(10).otherwise(3)
// equivalently:
someTest.ifTrue(10)(3)
Option
的相应 pimp :
class OptionExt[A](option: Option[A]) {
def ifNone[R](f: => R) = new Otherwise1(option match {
case None => Some(f)
case Some(_) => None
}, option.get)
def ifSome[R](f: A => R) = new Otherwise0(option match {
case Some(value) => Some(f(value))
case None => None
})
}
implicit def extendOption[A](opt: Option[A]): OptionExt[A] = new OptionExt[A](opt)
class Otherwise1[R, A1](intermediateResult: Option[R], arg1: => A1) {
def otherwise[S >: R](f: A1 => S) = intermediateResult.getOrElse(f(arg1))
def apply[S >: R](f: A1 => S) = otherwise(f)
}
Otherwise1
这样我们就可以方便地将展开的值传递给
ifSome
函数参数,但也适用于
otherwise
的函数参数关注
ifNone
.
关于scala - 在 Scala 中实现 ifTrue、ifFalse、ifSome、ifNone 等以避免 if(...) 和简单的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5654004/
在 Scala 中,我逐渐失去了 Java/C 以面向控制流的方式思考的习惯,并习惯于先获取我感兴趣的对象,然后通常应用类似 match 的东西。或 map()或 foreach()用于收藏。我非常喜
我是一名优秀的程序员,十分优秀!