2013-02-22 62 views
14

在Python中,我們有星號(或「*」或「unpack」)運算符,它允許我們解壓列表以方便使用傳遞位置參數。例如:是否有Python列表解壓(a.k.a.「*」)運算符的Scala等價物?

range(3, 6) 
args = [3, 6] 
# invokes range(3, 6) 
range(*args) 

在這個特殊的例子,它並沒有節省多少打字,因爲只有range兩個參數。但你可以想象,如果有更多的參數range,或者如果args從輸入源讀取,從另一個函數返回等,那麼這可能派上用場。

在斯卡拉,我一直無法找到相同的。考慮Scala的交互式會話中運行以下命令:

case class ThreeValues(one: String, two: String, three: String) 

//works fine 
val x = ThreeValues("1","2","3") 

val argList = List("one","two","three") 

//also works 
val y = ThreeValues(argList(0), argList(1), argList(2)) 

//doesn't work, obviously 
val z = ThreeValues(*argList) 

有沒有更簡潔的方式來做到這一點,除了在val y使用的方法是什麼?

+7

錯誤地標記爲重複,而不是。 Scala具有':_ *'運算功能,但它只能在定義端使用可變參數:例如'case class Things(xs:String *)' – 2013-02-22 23:01:58

回答

4

函數的功能類似於:tupled它將一個帶有n個參數的函數轉換爲一個帶有n元組類型參數的函數。

看到這個問題的更多信息:scala tuple unpacking

這種用於陣列的方法就沒有太大的意義,因爲它只會與同類型的多個參數的函數工作。

+0

一致認爲它沒有意義,因爲所有參數必須是相同的類型。在我正在考慮的特定用例中,'argList'實際上來自於分割作爲輸入提供的字符串,並且我會'隱式地def'一些轉換來將字符串轉換爲我試圖調用的函數所需的各種類型。但即使如此,我還是需要從List中構建一個Tuple。 – 2013-02-22 23:14:35

+1

有人構建了一個HList,它基本上是每個元素都有獨立類型的列表。可以將其轉換爲元組......只是一個想法。 – 2013-02-22 23:25:33

+1

@JensSchauder斯卡拉茲和無形者都會實現這個想法,儘管無形態需要更多。 – 2013-02-23 00:13:03

18

在scala中沒有直接的等價物。 您會發現最接近的是使用_*,它僅適用於可變參數方法。 例如,這裏是一個可變參數的方法的例子:

def hello(names: String*) { 
    println("Hello " + names.mkString(" and ")) 
} 

可與任意數量的參數一起使用:現在

scala> hello() 
Hello 
scala> hello("elwood") 
Hello elwood 
scala> hello("elwood", "jake") 
Hello elwood and jake 

,如果你有一個字符串列表,並希望通過他們這種方法,把它解壓的方式是通過_*

scala> val names = List("john", "paul", "george", "ringo") 
names: List[String] = List(john, paul, george, ringo) 
scala> hello(names: _*) 
Hello john and paul and george and ringo  
4

可以使用shapeless獲得對Python的一些方法,

Welcome to Scala version 2.11.0-20130208-073607-ce32c1af46 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_05). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> import shapeless._ 
import shapeless._ 

scala> import Traversables._ 
import Traversables._ 

scala> case class ThreeValues(one: String, two: String, three: String) 
defined class ThreeValues 

scala> val argList = List("one","two","three") 
argList: List[String] = List(one, two, three) 

scala> argList.toHList[String :: String :: String :: HNil].map(_.tupled).map(ThreeValues.tupled) 
res0: Option[ThreeValues] = Some(ThreeValues(one,two,three)) 

正如你所看到的,在Scala中需要更多的儀式與無形。這是因爲無形造成了編譯時間約束,這些約束在運行時保證是滿足的(不同於python,如果args的大小錯誤或包含錯誤類型的元素,python將在運行時失敗),而不是強制指定您希望列表的類型(在這種情況下恰好爲三個Strings),並準備處理不滿足該預期的情況(因爲結果明確爲的ThreeValues)。

相關問題