出于自我折磨的目的,我一直在尝试编写自己的if-elseif-else
构造实现(when-butWhen-otherwise
在我的案例中)。有趣的是,我写的东西在butWhen
之前没有一个点编译,并且用它编译,并且在otherwise
之前编译有和没有点的情况:
when(false) {
println(">> True")
}.butWhen(false) {
println(">> hello")
}.butWhen(false) { // Without the dot says "Boolean(false) does not take parameters"
println(">> Goodbye")
} otherwise {
println(">> Something else")
}
对于我未经训练的眼睛,butWhen
和其他方面的声明是相同的,它们返回相同的东西,所以看起来它们必须表现相同。此外,当我将otherwise
直接链接到when子句时,编译成功也没有点。
when-butWhen-otherwise
的代码:
trait ButWhenTrait {
def butWhen(b: Boolean)(op3: => Unit): ButWhenTrait
def otherwise(op2: => Unit) // {}
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait = {
if (b) {
op
DeadEnd
} else FalseWhen
}
}
object FalseWhen extends ButWhenTrait {
override def otherwise(op2: => Unit) { op2 }
override def butWhen(b: Boolean)(op2: => Unit) = {
if (b) {
op2
DeadEnd
} else {
FalseWhen
}
}
}
object DeadEnd extends ButWhenTrait {
override def otherwise(op: => Unit) {}
override def butWhen(b: Boolean)(op: => Unit) = { DeadEnd }
}
答案 0 :(得分:5)
由下一个限制引起的错误:Method Invocation的后缀表示法仅适用于 Arity-0 & Arity-1 方法。
可能的解决方案:
1)通过将调用拆分为2个对象来减少方法arity:
- 更新(错误修正) -
trait ButWhenTrait {
def butWhen(b: Boolean): ExecBlock
def otherwise(op: => Unit): Unit
}
trait ExecBlock {
// $ name of method for transfer execution function
def $(op : => Unit): ButWhenTrait
}
object NextExecBlock extends ExecBlock {
object next extends ButWhenTrait {
def butWhen(b: Boolean): ExecBlock = if(b) EndExecBlock else NextExecBlock
def otherwise(op: => Unit) { op }
}
def $(op : => Unit): ButWhenTrait = next
}
trait EmptyButWhenTrait {
object next extends ButWhenTrait {
def otherwise(op : => Unit) {}
def butWhen(b : Boolean) = EmptyExecBlock
}
}
object EndExecBlock extends ExecBlock with EmptyButWhenTrait {
def $(op : => Unit): ButWhenTrait = { op; next }
}
object EmptyExecBlock extends ExecBlock with EmptyButWhenTrait {
def $(op : => Unit): ButWhenTrait = next
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait =
if(b) EndExecBlock $ op else NextExecBlock $ op
}
比用法:
when(false) {
println(">> True")
} butWhen(false) $ {
println(">> hello")
} butWhen(false) $ {
println(">> Goodbye")
} otherwise {
println(">> Something else")
}
2)使用apply方法对boolean to object进行隐式对比:
trait ButWhenTrait {
def butWhen(op : ButWhenTrait): ButWhenTrait = op
def otherwise(op: => Unit) { op }
}
class ExecBlock(b : Boolean) {
private object next extends ButWhenTrait
private object end extends ButWhenTrait {
override def butWhen(op : ButWhenTrait) = end
override def otherwise(op : => Unit) {}
}
def apply(op : => Unit): ButWhenTrait = if(b) { op; end } else next
}
object when {
def apply(b: Boolean)(op: => Unit): ButWhenTrait = new ExecBlock(b)(op)
}
// AND implicit conversion:
implicit def boolToExec(b : Boolean): ExecBlock = new ExecBlock(b)
比用法(如你所料):
when(false) {
println(">> True")
} butWhen(false) {
println(">> hello")
} butWhen(false) {
println(">> Goodbye")
} otherwise {
println(">> Something else")
}