我正在编写一个生成 Scala 输出的代码生成器。
我需要以这样的方式模拟三元运算符,即导致“?”的标记保持不变。
例如转换表达式c ? p : q
to c something
。简单的if(c) p else q
不符合我的标准,因为它需要if(
before c
.
我的第一次尝试(仍然使用上面的 c/p/q )是
c match { case(true) => p; case _ => q }
我发现的另一个选择是:
class ternary(val g: Boolean => Any) { def |: (b:Boolean) = g(b) }
implicit def autoTernary (g: Boolean => Any): ternary = new ternary(g)
这让我可以写:
c |: { b: Boolean => if(b) p else q }
我喜欢第二个选项的整体外观,但是有没有办法让它不那么冗长?
Thanks
即使语法没有按照预期的顺序求值——它将条件绑定到第一个选项!——你也可以像这样创建自己的三元运算符:
class IfTrue[A](b: => Boolean, t: => A) { def |(f: => A) = if (b) t else f }
class MakeIfTrue(b: => Boolean) { def ?[A](t: => A) = new IfTrue[A](b,t) }
implicit def autoMakeIfTrue(b: => Boolean) = new MakeIfTrue(b)
诀窍是解释?
作为一种方法MakeIfTrue
将条件绑定到要在“true”情况下返回的对象的对象。所结果的IfTrue
对象现在使用|
方法作为评估条件的请求,如果条件为 true,则返回存储的 true 选项,如果条件为 false,则返回刚刚传入的选项。
请注意,我用过类似的东西=> A
而不是仅仅A
--by-name 参数--为了不计算表达式,除非它被实际使用。因此,您将只评估您实际需要的一面(就像 if 语句一样)。
让我们看看它的实际效果:
scala> List(1,3,2).isEmpty ? "Empty" | "Nonempty"
res0: java.lang.String = Nonempty
scala> (4*4 > 14) ? true | false
res1: Boolean = true
scala> class Scream(s: String) { println(s.toUpperCase + "!!!!") }
defined class Scream
scala> true ? new Scream("true") | new Scream("false")
TRUE!!!!
res3: Scream = Scream@1ccbdf7
(P.S.为了避免与 Actor 库混淆?
,你可能应该将其称为其他名称,例如|?
.)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)