什么时候Scala中的空白很重要?

The*_*ock 2 scala

在Scala中进行开发时,我似乎经常遇到白色空间问题,这些问题会对代码的含义产生意想不到的影响.

最近,我在尝试编写多行布尔表达式时出现问题,其中断行似乎导致编译错误,即

(oneVeryLongExpression < anotherVeryLongExpression) || ((a == b) && c);
Run Code Online (Sandbox Code Playgroud)

...编译得很好,但是,如果因为这些很长的表达而我很想分裂线...

(oneVeryLongExpression < anotherVeryLongExpression) 
  || ((a == b) && c);
Run Code Online (Sandbox Code Playgroud)

...它没有编译,这让我感到意外.

我发现我可以通过在整个表达式周围添加一组额外的括号来解决这个问题:

((oneVeryLongExpression < anotherVeryLongExpression) 
  || ((a == b) && c));
Run Code Online (Sandbox Code Playgroud)

...但我仍然想了解为什么Scala需要这个提示来忽略换行符.

在向另一个方向发展时我也遇到了问题:我偶尔将一个中等大小的Scala代码块转换为一组单行代码片段,以便将每个代码片段作为单行输入到不接受的基于Scala的shell中多行输入.

这是一个for-each的示例,我需要能够在我的shell中作为单行输入运行(对于那些对我正在做的事情感到好奇的人,我正在查看我的软件图表是否相等检查两侧的变量类型是否属于特定类型,以查找x.equals(y)应该使用的位置而不是:)x == y:

equalityChecks.foreach { node => {
  var lhsFound = false;
  var rhsFound = false;
  breakable {
    node.inEdges().foreach { edge => {
      if (nodesOfTypeT.contains(edge.originNode())) {
        if (edge.tagged(leftOperand)) {
          lhsFound = true;
        };
        if (e.taggedWith(rightOperand)) {
          rhsFound = true;
        };
        if (lhsFound && rhsFound) {
          doublyReachable.add(n);
          break; /* skip the rest of the edges and process next node */
        };
      }
    }}
  };
}};
Run Code Online (Sandbox Code Playgroud)

注意breakable块和三个if块之后的额外分号,至少其中一些是必要的,以便在删除换行符时保留代码的含义; 没有它们,它不会编译.

在什么情况下换行在Scala中具有语义含义?在添加或删除换行符之前,如何判断是否会改变代码的含义?

Arc*_*heg 5

(oneVeryLongExpression < anotherVeryLongExpression)在scala中是一个恰当的表达.当编译器遍历代码并满足此表达式并且在同一行中没有任何内容时,它会将其报告为正确的表达式.然后下一行|| ((a == b) && c);变得意外并产生错误.在这种情况下,您使用括号使编译器了解多行表达式是正确的.你也可以留||在第一行,使第一行不是有效的表达式:

(oneVeryLongExpression < anotherVeryLongExpression) ||
  ((a == b) && c);
Run Code Online (Sandbox Code Playgroud)

scala REPL也接受多行输入.只需输入:paste命令即可输入任何内容.按ctrl-D完成

至于分号,它们在scala中很少需要.我认为你需要在for-comprehensions中或者如果你将几个单独的表达式放在一行中.在你的榜样node => ...三个表达式的组成: var lhsFound = false,var rhsFound = falsebreakable {...}易碎形成一个大的表现,但它也从几形成if语句,所以你需要,因为他们是独立的表达式来分隔它们.当然,这仅适用于您将所有内容都作为单线程的情况.我仍然认为你不应该把这些分号 - 只需在REPL中使用粘贴模式.

我发现自己只在for-comprehensions或短模式匹配(通常是部分函数)中使用分号,我希望它们是单行

之前的PS分号}始终是可选的,因为它不会分离表达式.我相信分号在你的代码中,如果公司后= true,并break可以被删除.如果将所有这些代码放在一行中,则所有其他代码都是正确的