我是Scala的新手。我想知道是否可以使用方法调用定义一些优先级。例如,如果我有方法调用链:
someObject method1 param1 method2 param2 method3 param3
这可以等同于以下内容:
someObject.method1(param1).method2(param2.method3(param3))
或
someObject method1 param1 method2 (param2 method3 param3)
所以我希望method3优先于method2 ...
我想这样做的原因是我想开发一个DSL,所以我想避免尽可能多地使用点和圆括号。如果你们为我找到另一种解决方案,请随时告诉我。
答案 0 :(得分:12)
您必须使用具有特殊运算符字符的方法来影响Tomasz所暗示的优先级。这就是为什么许多Scala DSL大量使用运营商的原因。另外,如果你每天都不使用DSL,那么为什么有些DSL很难阅读呢。
给定只使用字母,下划线和数字的方法 - 你将无法影响事物,这是我在阅读规范后为自己整理的内容:
a.m(b)
可以写成a m b
。任何不需要参数的方法都可以用作后缀运算符:a.m
可以写成a m
。
后缀运算符的优先级低于中缀运算符,因此foo bar baz
表示foo.bar(baz)
,而foo bar baz bam
表示(foo.bar(baz)).bam
和{{1 }}表示foo bar baz bam bim
。
因此,根本不知道您的方法签名是什么,以下代码(因为它是所有字母数字):
(foo.bar(baz)).bam(bim)
将被解析为:
someObject method1 param1 method2 param2 method3 param3
如果您将someObject.method1(param1).method2(param2).method3(param3)
重命名为method3
或|*|
或任何有意义的操作符,您可以实现所需目标:
+:+
例如,看看差异:
someObject method1 param1 method2 param2 |*| param3
// same as
someObject.method1(param1).method2(param2.|*|(param3))
答案 1 :(得分:4)
此行为在 Scala语言规范的第6.12.3 Infix Operations章中定义。
简而言之:默认情况下,从左到右调用方法,但有一些例外。这些例外仅用于支持数学运算符优先级。所以当你有两个名为*
和+
的函数时:
a + b * c
这将始终转换为:
a.+(b.*(c))
这里函数的第一个名称控制优先级。但是对于普通功能,您无法控制订单。想一想 - 这实际上会造成破坏性和非常难以维护的代码。
另见(不完全重复?):Operator precedence in Scala。