如何在 Scala 中定义保留前导标记的三元运算符?
我正在编写一个生成 Scala 输出的代码生成器。
我需要以这样的方式模拟三元运算符,即导致“?”的标记保持完好无损。
例如转换表达式 c ? p : q
到 c 某事
。简单的 if(c) p else q
不符合我的标准,因为它需要将 if(
放在 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 }
我喜欢第二个选项的整体外观,但是有没有办法让它不那么冗长,
谢谢?
I'm writing a code generator which produces Scala output.
I need to emulate a ternary operator in such a way that the tokens leading up to '?' remain intact.
e.g. convert the expression c ? p : q
to c something
. The simple if(c) p else q
fails my criteria, as it requires putting if(
before c
.
My first attempt (still using c/p/q as above) is
c match { case(true) => p; case _ => q }
another option I found was:
class ternary(val g: Boolean => Any) { def |: (b:Boolean) = g(b) } implicit def autoTernary (g: Boolean => Any): ternary = new ternary(g)
which allows me to write:
c |: { b: Boolean => if(b) p else q }
I like the overall look of the second option, but is there a way to make it less verbose?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
即使语法没有按照预期的顺序求值——它将条件绑定到第一个选项!——你也可以像这样创建自己的三元运算符:
技巧是将
?
解释为MakeIfTrue
对象上的方法,将条件绑定到要在“true”情况下返回的对象。生成的IfTrue
对象现在使用|
方法作为评估条件的请求,如果条件为 true,则返回存储的 true 选项,或者返回刚刚传入的选项如果是假的。请注意,我使用了诸如
=>; 之类的东西。 A
而不仅仅是A
(按名称参数),以便除非实际使用表达式,否则不会计算表达式。因此,您将只评估您实际需要的一面(就像 if 语句一样)。让我们看看它的实际效果:
(PS 为了避免与 Actor 库
?
混淆,您可能应该将其称为|?
之类的其他名称。)Even though the syntax doesn't evaluate in the expected order--it binds the conditional to the first option!--you can make your own ternary operator like this:
The trick is to interpret
?
as a method on aMakeIfTrue
object that binds the condition to the object to return in the "true" case. The resultingIfTrue
object now uses the|
method as a request to evaluate the condition, returning the stored true option if the condition is true, or the just-passed-in one if it's false.Note that I've used stuff like
=> A
instead of justA
--by-name parameters--in order to not evaluate the expression unless it's actually used. Thus, you'll only evaluate the side that you actually need (just like an if statement).Let's see it in action:
(P.S. To avoid confusion with the Actor library
?
, you probably ought to call it something else like|?
.)让我们保持简单:
Java:
Scala:
除了简单之外,它还清晰且快速,因为:不分配不需要的对象,使垃圾收集器不受影响(因为它总是应该如此)并更好地利用处理器缓存。
Let's keep it simple:
Java:
Scala:
Besides simplicity, it is clear and fast because: do not allocate objects you don't need, keeps the garbage collector out of equation (as it always should be) and makes better use of processor caches.
您可以使用类似这样的
代码:此代码将任何布尔值转换为具有名为
?
的方法的匿名类型。根据布尔值的不同,此方法将返回 TernarySecond 或 TernaryThird。它们都有一个名为>
的方法,该方法分别返回第二个操作数或第三个操作数。You could use something like this
This code converts any boolean value to an anonymous type that has a method called
?
. Depending on the value of the boolean, this method will either returnTernarySecond
orTernaryThird
. They both have a method called>
which returns the second operand or the third one respectively.三元运算符将我的改进添加到 Rex Kerr 和 Michel Kramer 的最佳实现中:
。
请注意,相对于
if else
的改进不仅仅是节省了 6 个字符。 Scala IDE 的关键字语法颜色对于if
、else
、null
和true
,在某些情况下有更好的对比度(本网站当前呈现的语法着色未显示这一点):Ternary operator which adds my improvement to the best of Rex Kerr’s and Michel Krämer’s implementations:
.
Note the improvement over
if else
is not just the 6 characters saved. With Scala IDE’s syntax coloring on keywords being the same (e.g. purple) forif
,else
,null
, andtrue
, there is better contrast in some cases (which isn't shown by the syntax coloring below as currently rendered on this site):