Scala - 方法优先级

Pet*_*ter 17 methods scala

我是Scala的新手.我想知道是否可以使用方法调用定义一些优先级.例如,如果我有方法调用链:

someObject method1 param1 method2 param2 method3 param3
Run Code Online (Sandbox Code Playgroud)

这可以等同于以下内容:

someObject.method1(param1).method2(param2.method3(param3))
Run Code Online (Sandbox Code Playgroud)

要么

someObject method1 param1 method2 (param2 method3 param3)
Run Code Online (Sandbox Code Playgroud)

所以我希望method3优先于method2 ...

我想这样做的原因是我想开发一个DSL,所以我想避免尽可能多地使用点和圆括号.如果你们为我找到另一种解决方案,请随时告诉我.

huy*_*hjl 12

您必须使用具有特殊运算符字符的方法来影响Tomasz所暗示的优先级.这就是为什么许多Scala DSL大量使用运营商的原因.另外,如果你每天不使用它们,一些DSL很难读懂.

给定只使用字母,下划线和数字的方法 - 你将无法影响事物,这是我在阅读规范后为自己整理的内容:

  • 任何采用单个参数的方法都可以用作中缀运算符:a.m(b)可以编写a m b.
  • 任何不需要参数的方法都可以用作后缀运算符:a.m可以编写a m.

  • Postfix的运营商比中缀运算符的优先级低,因此foo bar baz意味着foo.bar(baz)尽管foo bar baz bam手段(foo.bar(baz)).bamfoo bar baz bam bim方式(foo.bar(baz)).bam(bim).

因此,根本不知道您的方法签名是什么,以下代码(因为它是所有字母数字):

someObject method1 param1 method2 param2 method3 param3
Run Code Online (Sandbox Code Playgroud)

将被解析为:

someObject.method1(param1).method2(param2).method3(param3)
Run Code Online (Sandbox Code Playgroud)

如果您重命名method3|*|或者+:+任何有意义的操作符,您可以实现您想要的:

someObject method1 param1  method2 param2 |*| param3
// same as
someObject.method1(param1).method2(param2.|*|(param3))
Run Code Online (Sandbox Code Playgroud)

例如,看看差异:

implicit def pimp(s:String) = new {
    def |*|(t:String) = t + s
    def switch(t:String) = t + s 
}

scala> "someObject" concat "param1" concat "param2" |*| "param3"
res2: java.lang.String = someObjectparam1param3param2

scala> "someObject" concat "param1" concat "param2" switch "param3"
res3: java.lang.String = param3someObjectparam1param2
Run Code Online (Sandbox Code Playgroud)


Tom*_*icz 4

此行为在Scala 语言规范第 6.12.3 中缀操作一章中定义。

简而言之:默认情况下,方法是从左到右调用的,但有一些例外。引入这些例外只是为了支持数学运算符优先级。因此,当您有两个名为*和 的函数时+

a + b * c
Run Code Online (Sandbox Code Playgroud)

这将始终被翻译为:

a.+(b.*(c))
Run Code Online (Sandbox Code Playgroud)

这里函数的名字控制优先级。但是对于普通函数,您无法控制顺序。想想看 - 这实际上会造成严重破坏并且代码非常难以维护。

另请参阅(不太重复?):Scala 中的运算符优先级