Ответ 1
Чтобы быть ясным, допустимым является код Python:
def foo(bar1, bar2, bar3=None, bar4=1): print("bar1="+str(bar1)+" bar2="+str(bar2)+" bar3="+str(bar3)+" bar4="+str(bar4))
x=[1,7]
y={'bar3':True, 'bar4':9}
foo(*x,**y)
Однако не существует аналогичного синтаксиса Scala. Есть некоторые подобные вещи, но основная причина, по которой это никогда не будет возможным, заключается в том, что она нарушит проверку типа компиляции, требуемую Scala. Давайте посмотрим более внимательно.
Причины
Сначала подумайте о части varargs. Здесь вы хотите иметь возможность передавать произвольный список аргументов и заполнять соответствующие параметры функции. Это никогда не будет работать в Scala, потому что для проверки типа требуется, чтобы параметры, переданные в функцию, были действительны. В вашем сценарии foo()
может принимать список параметров x
длины два, но не менее. Но так как любой Seq
может иметь произвольное количество параметров, как мог бы знать, что прохождение x
проходит, это действительно во время компиляции?
Во-вторых, подумайте о аргументах ключевого слова. Здесь вы просите функцию принять произвольный Map
аргументов и значений. Но у вас возникает та же проблема: как средство проверки типа компиляции знает, что вы передаете все необходимые аргументы? Или, кроме того, что они правильные типы? В конце концов, пример, который вы приводите, представляет собой карту, содержащую как логические, так и Int, которые будут иметь тип Map[String, Any]
, и как бы проверивший тип знал, что это будет соответствовать вашим типам параметров?
Некоторые решения
Scala varargs
Вы можете сделать некоторые подобные вещи, но не это точно. Например, если вы определили свою функцию для явного использования varargs, вы можете перейти в Seq:
def foo(bar1: Int*) = println(f"bar1=$bar1")
val x = Seq(1, 2)
foo(x:_*)
Это работает, потому что Scala знает, что ему нужна только последовательность из нуля или более аргументов, а Seq всегда будет содержать ноль или несколько элементов, поэтому он будет соответствовать. Кроме того, он работает только в том случае, если типы совпадают; здесь он ожидает последовательность интов и получает ее.
tupled
Другое, что вы можете сделать, это передать кортеж аргументов:
def foo(bar1: Int, bar2: Int, bar3: Boolean = false, bar4: Int = 1) = println(f"bar1=$bar1 bar2=$bar2 bar3=$bar3 bar4=$bar4")
val x = (1, 2, true, 9)
(foo _).tupled(x)
Опять же, это работает, потому что Scala checker типа может проверить правильность аргументов. Функция требует четырех аргументов типов Int, Int, Boolean и Int, а поскольку кортеж в Scala имеет фиксированную длину и известные (и, возможно, разные) типы для каждой позиции, средство проверки типов может проверить, что аргументы соответствуют ожидаемым параметрам.