Где вы разделяете длинные сигнатуры функций Scala?

#scala #coding-style

#scala #стиль кодирования

Вопрос:

Определение, подобное

 def foo(x: Int) = x   1
  

красиво и коротко, и выглядит красиво, но когда сама подпись становится неудобно длинной,

 def foo[T <: Token[T]](x: ArrayBuffer[T], y: T => ArrayBuffer[() => T]): (T, T, BigDecimal) = {
    // ...
}
  

Я не знаю, где это разделить. Я нахожу, что все следующее выглядит неуклюже:

 def foo(
    x: Int,
    y: Int
): Int = {
    // ...
}

def foo(
        x: Int,
        y: Int
    ): Int =
{
    // ...
}

def foo(
        x: Int,
        y: Int
    ): Int
= {
    // ...
}

def foo(
        x: Int,
        y: Int
    ):
Int = {
    // ...
}
  

Но, учитывая, что мне придется привыкнуть к одному из них, который вызовет наименьшее раздражение у моих товарищей по команде?

Комментарии:

1. Я лично использую верхнюю, поскольку она наиболее совместима со всеми другими отступами. Но я также думаю, что это больше для программистов. Вопрос SE, а не вопрос SO.

Ответ №1:

В руководстве по стилю Scala нечего сказать по этому поводу. На самом деле он рекомендует использовать методы с меньшим количеством параметров :-).

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

 foo(someVeryLongFieldName,
    andAnotherVeryLongFieldName,
    "this is a string",
    3.1415)
  

Лично в вашем случае я бы разделился в соответствии с правилом «держать подобные вещи вместе»:

 def foo[T <: Token[T]]
       (x: ArrayBuffer[T], y: T => ArrayBuffer[() => T])
       : (T, T, BigDecimal) = {
  // ...
}
  

Таким образом, параметры находятся в одной строке, возвращаемый тип — в одной строке, а ограничение типа — в одной строке.

Комментарии:

1. docs.scala-lang.org/style / … теперь рекомендуется делать отступы в аргументах вызова функции на два пробела, а не выравнивать их по первой круглой скобке.

Ответ №2:

В Haskell сигнатуры длинных типов часто записываются таким образом:

 someFunc :: (Some Constraints Go Here)
         => Really Long Arg1 Type
         -> Really Long Arg2 Type
         -> Really Long Result Type
somefunc x y = ...
  

Чтобы перевести этот хаскелизм в Scala,

 def foo [ T <: Token[T] ]
        ( x : ArrayBuffer[T]
        , y : T => ArrayBuffer[() => T]
        )   : (T, T, BigDecimal) = {
    // ...
}
  

Вот как я бы это сделал. Не уверен, насколько это приемлемо для сообщества Scala.

Комментарии:

1. Из приведенного выше сравнения синтаксиса Haskell и Scala я понял, сколько шума создают запятые, круглые скобки и точки с запятой.