实际上,我从来没有遇到过这个问题,而且我犯了很多愚蠢的错误。我怀疑你完全有能力学会不跳过 else 语句。(请注意,大括号没有任何帮助;您仍然可以跳过else
中间的那个。)
如果您真的真的发现这是一个问题,您可以滥用以下match
声明:
true match {
case _ if f1(bar) => 0
case _ if f2(bar) => 1
case _ => -1
}
这将防止你犯任何错误。或者你可以自己写一个实用方法:
trait Conditional[+A] {
def apply[B >: A](p: => Boolean, b: => B): Conditional[B]
def or[B >: A](default: => B): B
}
class FoundIt[+A](it: A) extends Conditional[A] {
def apply[B >: A](p: => Boolean, b: => B) = this
def or[B >: A](default: => B) = it
}
class NothingYet[+A] extends Conditional[A] {
def apply[B >: A](p: => Boolean, b: => B) = {
if (p) new FoundIt(b) else this
}
def or[B >: A](default: => B) = default
}
def ifelse[A](p: => Boolean, a: => A) = (new NothingYet[A]).apply(p,a)
ifelse( f1(bar), 0 )( f2(bar), 1 ) or -1
这对于长表达式来说有点乱,所以你也可以(:paste
如果你想让它在那里工作,可以把它放在一个大块的 REPL 中):
trait Predicate[+A] {
def Or(p: => Boolean): Loadable[A]
def Else[B >: A](default: => B): B
}
trait Loadable[+A] {
def Then[B >: A](b: => B): Predicate[B]
}
object NotYetTrue extends Predicate[Nothing] {
def Or(p: => Boolean) = if (p) ActuallyLoad else SkipLoading
def Else[B >: Nothing](default: => B) = default
}
object SkipLoading extends Loadable[Nothing] {
def Then[B >: Nothing](b: => B) = NotYetTrue
}
object ActuallyLoad extends Loadable[Nothing] {
def Then[B >: Nothing](b: => B) = new Loaded[B](b)
}
class Loaded[+A](a: A) extends Predicate[A] with Loadable[A] {
def Or(p: => Boolean) = this
def Else[B >: A](default: => B) = a
def Then[B >: A](b: => B) = this
}
def If(p: => Boolean): Loadable[Nothing] = NotYetTrue.Or(p)
现在唯一的技巧是你必须:paste
在 REPL 中使用来编写一个多行语句,并将延续放在上一行的末尾:
If (f1(bar)) Then 0 Or
(f2(bar)) Then 1 Else
-1
您还可以Then { 0
在一行上使用并在下一行重新开始} Or
,或者用括号/大括号和点编写所有内容(这是 REPL 友好的):
If (f1(bar)) .Then (0) .
Or (f2(bar)) .Then (1) .
Else (-1)
无论如何,所有这些技巧都很好地说明了如何使用 Scala 构建复杂的 DSL,但并不是解决问题的最佳方法。你应该学会对 if/else 语句更加小心;否则,人们会对你为什么不以标准方式做事感到困惑。(如果它是性能关键的,它可能会很慢——match
非常好,但在If
高性能循环中魔法并不好。)