3

У меня сложнее понять, когда я могу или не могу опустить скобки и/или периоды, и как это чередуется с _.Именованные параметры vs _, точечная нотация против операции infix, фигурные и круглые скобки при использовании функций более высокого порядка в Scala

Конкретный случай, который я имел с этим был

val x: X = ??? 
val xss: List[List[X]] = ??? 
xss map x :: _ //this doesn't compile 
xss map _.::(x) //this is the same as the above (and thus doesn't compile) 

выше два кажутся идентичными xss.map(_).::(x)

xss map (x :: _) //this works as expected 
xss map {x :: _} //this does the same thing as the above 

тем временем, следующий также не:

xss.map xs => x :: xs //';' expected but '=>' found. 
xss.map x :: _ //missing arguments for method map in class List; follow this method with `_' if you want to treat it as a partially applied function 
//so when I try following the method with _, I get my favourite: 
xss.map _ x :: _ //Cannot construct a collection of type That with elements of type B based on a collection of type List[List[Main.X]] 
//as opposed to 
xss map _ x :: _ //missing parameter type for expanded function ((x$1) => xss.map(x$1).x(($colon$colon: (() => <empty>)))) 

Right теперь я часто играю «переключать символы, пока они не компилируются», которые, как я считаю, являются субоптимальная стратегия программирования. Как это все работает?

+2

Вы видели http://stackoverflow.com/questions/2173373/scala-foreach-strange-behaviour? – sschaef

+0

Пока нет, спасибо. Ищу. – Martijn

+1

Это должно помочь с проблемой того, где оставить круглые скобки/точки: http://stackoverflow.com/questions/1181533/what-are-the-precise-rules-for-when-you-can-omit-parenthesis- dots-braces-f – sschaef

ответ

2

Сначала нам нужно провести различие между xss.map(f) и xss map f. Согласно Scala Documentation, любой метод, который принимает один параметр, может использоваться как оператор инфикса.

Фактически map method in List является одним из этих методов. Не обращая внимания на полную подпись и тот факт, что это унаследованный от TraversableLike, подпись выглядит следующим образом:

final def map[B](f: (A) ⇒ B): List[B] 

Так оно принимает один параметр, а именно f, который является функцией с типом A => B. Так что если у вас есть function value определяется как

val mySize = (xs:List[Int]) => xs.size 

вы можете выбрать между

xss.map(mySize) 

или

xss map mySize 

Это вопрос предпочтений, но в соответствии с Scala Style Guide, для этого случая, то последнее предпочтительнее, если только это не является частью сложного выражения, где лучше придерживаться точечной нотации.

Обратите внимание, что если вы решите использовать точечную нотацию, вам всегда нужно квалифицировать приложение-функцию с помощью скобок! Вот почему ни один из следующих компиляторов не работает успешно.

xss.map xs => x :: xs // Won't compile 
xss.map x :: _ // Won't compile 
xss.map _ x :: _ // Won't compile 

Но большую часть времени вместо того, чтобы передать значение функции вам нужно передать function literal (ака anonymous function). В этом случае снова, если вы используете точечную нотацию, вам нужно что-то вроде xss.map(_.size). Но если вы используете нотацию infix, это будет вопросом приоритета.

Например

xss map x :: _ // Won't compile! 

не работает из-за приоритета операторов. Поэтому вам нужно использовать скобки, чтобы устранить ситуацию для компилятора на xss map (x :: _).

Использование фигурных скобок вместо скобок имеет очень четкое и простое правило. Опять же любая функция, которая принимает только один параметр, может быть применена с фигурными скобками вместо скобок, как для инфиксных, так и для точечных обозначений.Таким образом, будут скомпилированы следующие утверждения.

xss.map{x :: _} 
xss map {x :: _} 

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

Для этого вы можете обратиться к Scala Style Guide и Martin Odersky's talk in Scala Days 2013, что касается стиля кодирования Scala. Также вы всегда можете обратиться за помощью к IDE, чтобы рефакторинг кода был более кратким.

+0

отличный ответ, спасибо. Что касается плагина Eclipse для рефакторинга моего кода - по моему опыту, который заканчивается неудачно, хотя я хорошо разбираюсь в intellij – Martijn

+0

Я отлично проведу время с [IntelliJ IDEA Scala Plugin] (http://plugins.jetbrains.com/ плагин /? ID = 1347). Он автоматически обнаруживает части кода, которые могут быть проще. Например, если вы пишете 'xss map (mySize)', это предложит удалить круглые скобки. Даже если вы пишете 'xss map (mySize (_))', он сначала предлагает удалить ненужный '_', а затем после удаления, он предлагает удалить скобки. Он достаточно умен, чтобы обнаружить большинство распространенных проблем и запахов кода. –

Смежные вопросы