10

Scala 是一种有趣的语言,它声称简洁、可扩展(通过在库而不是编译器中指定许多特性)并支持 DSL。在尝试实现这一点时,它有很多运算符以及编译器调整(例如,支持中缀运算符,例如:_* 以展平序列)。

我发现许多运算符(“Scala 编程”索引中的 2½ 页)和编译器调整令人困惑。公平地说,许多运算符都是从 C 等人借来的传统算术/布尔运算符)。

有人告诉我,这有一些基本的句法规则作为基础,我认为如果我知道这些,就会减轻我的认知负担。

是否有一些规则(如果有,它们是什么)还是我注定要学习库中的许多“运算符”方法和隐式?

4

3 回答 3

7

有两种方法可以理解您关于运营商的问题:

  1. Scala 编译器如何处理运算符的规则是什么?(语言规则)
  2. 管理库中如何定义运算符的规则是什么?(运营商定义)

语言规则

确实有规律。我会让你确定你是否认为它们“很少”。与 Scala 的大部分内容一样,您可以在Language Reference的第 6.12 节中找到它们。

最重要的位:

  • 唯一接受的前缀运算符是+,-和.!~

  • 任何不带参数的方法都可以用作后缀运算符。

  • 任何采用一个参数的方法都可以用作中运算符。然而,这些操作的优先级受制于特定规则,可能主要是为了使算术和其他表达式被视为人们所期望的。优先级由运算符/方法名称的第一个字符确定,并且与您对 C 或 Java 的期望相匹配。

  • 所有中缀运算符都是左结合运算符,以 . 结尾的运算符除外:。典型的例子包括::+:

所以基本上有四个规则。我鼓励您阅读规范以获得更多见解。

运算符定义

运算符定义的选择取决于库设计者。例如,Scala 集合库使用一组相对较小且一致的运算符(++--**+=-=++=--=+:等)。解析器组合器带有一个更奇特的集合,一些库起初可能完全无法理解,因为它们的自定义运算符定义(想到 sbt 或 Lift,尽管这只是我个人的看法)。

这已被认为是潜在问题的根源,Scala 风格指南对符号方法名称(自定义运算符)有这样的说法:

避免!尽管 Scala 在某种程度上促进了 API 设计的这一领域,但不应轻易定义具有符号名称的方法,特别是当符号本身是非标准的时(例如,>>#>>)。作为一般规则,符号方法名称有两个有效的用例:

  • 特定领域的语言(例如actor1 ! Msg
  • 逻辑数学运算(例如a + bc :: d
于 2012-11-10T14:04:11.140 回答
1

Scala 对操作符没有特殊处理

摘自《Scala 2ed 编程》一书

任何方法都可以是运算符

在 Scala 中,运算符不是特殊的语言语法:任何方法都可以是运算符。使方法成为运算符的原因在于您如何使用它。当你写“s.indexOf('o')”时,indexOf 不是一个操作符。但是当你写“ s indexOf 'o' ”时, indexOf 是一个运算符,因为你是在运算符符号中使用它。

我在您所指的索引中找不到 2 1/2 页。

Scala 运算符始终可用作在某些对象上定义的方法。这也与任何值在 scala 中表示为对象的事实一致,这与 Java 对原始类型的特殊遗留处理不同。

scala 底层实现可以利用原语在字节码级别提高性能,但这对最终用户是透明的。

运营商

所以这里的规则很简单:每个运算符实际上都是在某种类型上定义的方法。运算符中缀符号只是一个可读性问题,例如

val sum = 1 + 2

读起来比

val sum = 1.+(2)

这种符号也是构建具有“自然感觉”的 dsl 的基础。测试库ScalaSpecs清楚地证明了这一点。

特殊的编译器规则

正如您所说,有限数量的“编译器调整”可用于上述目的,以允许更清晰和更易于理解的代码。

可以在此处找到这些“调整”的相关摘要

于 2012-11-10T11:35:05.103 回答
1

所有信息都可以在stackoverflowspec中找到。

这是我关于从哪里开始的建议:

  1. 了解如何将标识符连续解析为操作数和运算符。请参阅我的回答何时在 Scala 中缀表示法中使用括号来讨论此主题。
  2. 记住足够多的运算符优先级列表。就个人而言,我只记得算术+, -, *,/的那些字母的优先级最低,而奇怪的 unicode 字母的优先级最高。对于其余部分,我添加括号或只是猜测优先级将按照 DSL 设计者的意图或在 Java 中的方式“解决”。
  3. 学习列表的x :: xsandxs ::: ys运算符,因为它们非常流行并且与右侧相关联,因为它们以 . 结尾:
  4. Optionally, if you are curious, have a cursory look at the section 6.12 Prefix, Infix, and Postfix Operations of the spec so that you'll know in some corner of your brain that there are specifics with respect with operator having = and prefix operators.

Finally, one last word of advice. Do not try to learn all operators, do not assume you should know all operator meanings to use the language effectively. That is unless you have learned other languages by reading and remembering the complete API.

于 2012-11-10T19:02:48.193 回答