Scala - метод приоритета - PullRequest
       2

Scala - метод приоритета

17 голосов
/ 29 сентября 2011

Я новичок в Скале.Интересно, можно ли определить какой-то приоритет с вызовами методов.Например, если у меня есть цепочка вызовов методов:

someObject method1 param1 method2 param2 method3 param3

, это может быть эквивалентно следующему:

someObject.method1(param1).method2(param2.method3(param3))

или

someObject method1 param1 method2 (param2 method3 param3)

Так что яхочу, чтобы method3 имел приоритет над method2 ...

Причина, по которой я хочу это сделать, заключается в том, что я хочу разработать DSL, поэтому я хочу избегать использования точек и скобок в максимально возможной степени.Если вы, ребята, найдете для меня другое решение, не стесняйтесь, дайте мне знать.

Ответы [ 2 ]

12 голосов
/ 29 сентября 2011

Вам придется использовать методы со специальными символами оператора, чтобы влиять на приоритет, как подразумевает Томаш. Отчасти поэтому многие Scala 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, а 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))

Например, чтобы увидеть разницу:

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
4 голосов
/ 29 сентября 2011

Это поведение определено в главе 6.12.3 Операции с инфиксами из Спецификация языка Scala .

Короче говоря: методы вызываются слева направо по умолчаниюс некоторыми исключениями.Эти исключения были введены только для поддержки приоритета математических операторов.Поэтому, когда у вас есть две функции с именами * и +:

a + b * c

Это всегда будет переводиться в:

a.+(b.*(c))

Здесь первое имя функции управляет приоритетом,Однако для обычных функций вы не можете контролировать порядок.Подумайте об этом - это на самом деле вызовет хаос и ужасно не поддерживаемый код.

См. Также (не совсем дубликат?): Приоритет оператора в Scala .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...