具有两个块的自定义控制结构

Custom control structure with two blocks

我是 Scala 的新手,在阅读一些教程和文档时,我尝试定义自定义控制结构。

所以我尝试实现一个隐式 class MyBoolean ,它提供一个带有两个参数列表的 ? 方法。第一个参数是一个块,如果 MyBoolean 为真,则执行第二个参数,如果 MyBoolean 为假,则执行第二个参数。

下面是生成的控制结构的语法示例:

true ? {println("true")} {println("false")};

所以本质上只是一个简单的 if-else 语句,作为布尔方法实现。

这是我的实现:

object Test extends App {
    implicit class MyBoolean(val value: Boolean) {
        def ? (body1: => Unit)(body2: => Unit){
            if (value) body1;
            else body2
        }
    }

    override def main(args: Array[String]): Unit = {
//      true ? {println("true")} {println("false")}; //--> compiler error
      true.? {println("true")} {println("false")}; // works fine...
    }
}

我面临的问题是我使用预期语法(在 Eclipse 中)遇到以下编译器错误:

missing arguments for method ? in class MyBoolean; follow this method with `_' if you want to treat it as a partially applied function

只有在方法 ? 之前明确添加点 . 才有效。

在 Scala 中调用方法时点不应该是可选的吗?有什么我想念的吗?

这是 Scala 语法中最奇怪的问题之一。您仍然可以使用带多个参数列表的无点样式 ,但您必须使用括号 (?!)

对对象、方法和第一个参数列表进行分组
(true ? {println("true")}) {println("false")}

工作正常。

为什么会这样?使用 /::\ 折叠符号非常方便;然后你可以将你的第一个元素与它应该 运行 通过的集合组合在一起。

对于其他一切,充其量是有问题的。

无论如何,你都被括号或点卡住了。

在调用 1 参数 方法时,点是可选的,但该语法不适用于 2 参数方法,即使在柯里化时也是如此(除非 @RexKerr 建议您括起来)。

您可以通过 "manual" currying 使其工作:编写一个单参数方法,returns 一个具有应用的对象:

class PartiallyApplied(value: Boolean, body1: => Unit) {
  def apply(body2: => Unit) = if (value) body1; else body2
}

class MyBoolean...
  def ? (body1: => Unit) = new PartiallyApplied(value, body1)

Shouldn't the dot be optional in Scala when calling methods?

有点像,但这并不完全准确。

在这些情况下,确实如此:

  • a.b(c)可以写成a b c
  • a.b(c, d)可以改写为a b (c, d).

来自 language spec 节 6.12.3,中缀操作:

The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op e1, …, en. This expression is the interpreted as e.op(e1, …, en).

A left-associative binary operation e1 op e2 is interpreted as e1.op(e2).

但是a.b(c)(d)形式的表达式没有相应的规则。不过,我不太确定为什么。在我看来,a b {c} {d} 是一种完全合理的写法。