<p>为了清楚起见,以下是有效的Python代码:</p>
<pre><code>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)
</code></pre>
<p>但是,没有类似的Scala语法。有一些类似的事情,但这永远不可能的主要原因是,它会违反Scala所要求的编译时类型检查。我们再仔细看看。</p>
<h2>原因</h2>
<p>首先,考虑varargs部分。在这里,您希望能够传入任意长度的参数列表,并让它填充相关的函数参数。这在Scala中是行不通的,因为类型检查器要求传递到函数中的参数是有效的。在您的场景中,<code>foo()</code>可以接受长度为2的参数列表,但不能小于2。但是,由于任何<code>Seq</code>都可以有任意数量的参数,类型检查器如何知道正在传递的<code>x</code>在编译时是有效的?</p>
<p>其次,想想keywword的论点。在这里,您要求函数接受参数和值的任意<code>Map</code>。但您也遇到了同样的问题:编译时类型检查器如何知道您正在传递所有必需的参数?或者,更进一步说,它们是正确的类型?毕竟,您给出的示例是一个同时包含布尔值和Int的映射,它将具有类型<code>Map[String, Any]</code>,那么类型检查器如何知道这将匹配您的参数类型?</p>
<h2>一些解决方案</h2>
<h3>斯卡拉变量</h3>
<p>你可以做一些类似的事情,但不是这样。例如,如果将函数定义为显式使用varargs,则可以传入一个Seq:</p>
<pre><code>def foo(bar1: Int*) = println(f"bar1=$bar1")
val x = Seq(1, 2)
foo(x:_*)
</code></pre>
<p>这是因为Scala知道它只需要一个包含零个或多个参数的序列,而Seq总是包含零个或多个项,所以它匹配。此外,只有当类型也匹配时,它才起作用;在这里,它需要一个int序列,并得到它。</p>
<h3><code>tupled</code></h3>
<p>另一种方法是传入参数的元组:</p>
<pre><code>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)
</code></pre>
<p>同样,这是因为Scala的类型检查器可以验证参数是否有效。该函数需要四个参数,类型为Int、Int、Boolean和Int,由于Scala中的元组具有固定的长度,并且每个位置都有已知(可能不同)的类型,因此类型检查器可以验证参数是否与预期参数匹配。</p>