2013-12-17 97 views
3

斯卡拉的<-箭頭似乎有點奇怪。大多數操作符都是作爲函數的某個地方在某個數據類型上直接或隱式地定義的。另一方面,<-僅在for理解之外似乎不可用,其中它充當用於表示單變量上下文中的新變量的綁定的語法元素(通過map)。是< - 只能由編譯器訪問

這是我能想到的唯一實例,Scala有一個只能在特定上下文中使用的操作符看上去的語法元素,而不是實際的函數。

我錯了關於如何<-的作品?這是編譯器使用的特殊情況符號,還是開發人員在編寫自己的代碼時可以使用這種行爲的某種方式?

例如,纔有可能寫一個宏變換

forRange (i <- 0 to 10) { print(i) } 

{ var i = 0; while (i <= 10) { print(i) } } 

代替它的標準map等效?據我所知,for上下文之外的i <- ...的任何用法都會由於引用未知值而導致異常。

回答

6

總之,是的<-是斯卡拉的保留運算符。這是一個編譯器。

的foreach

foreachfor yield之間有很強的區別,但語法只是語法糖,在編譯時改變。

for (i <- 1 to 10) { statement }表達被翻譯成:

Range.from(1, 10).foreach(..) 

多個變量: for (i <- 1 to 10; y <- 2 to 100) {..}變爲:

Range.from(1, 10).foreach( el => {Range.from(2, 100).foreach(..)});

隨着由下式給出的所有變體形式:

for (x <- someList) = someList.foreach(..)

簡而言之,他們都得到了脫糖至foreach聲明。被調用的具體的foreach由所使用的集合給出。

對於產量

for yield語法糖flatMapmapstay in the monad規則適用於此處。

for (x <- someList) yield {..}被翻譯成someList.flatMap(..)

連鎖經營成爲map/flatMap連擊分層鏈:

for { x <- someList; y <- SomeOtherList } yield {}變爲:

someList.flatMap(x => { y.flatMap(..) });等。

的一點是,<-操作無非是語法糖更使代碼更易讀,但它總是被在編譯時更換。

爲了強調羅布的點

羅布使得其他Scala的語法糖很好的例子。

上下文結合

package somepackage; 
class Test[T : Manifest] {} 

也被轉換爲:

class Test[T](implicit evidence: Manifest[T])

爲了證明這一點,儘量別名類型與結合上下文:

type TestAlias[T : Manifest] = somepackage.Test // error, the : syntax can't be used.。 可能很容易看到: Manifest零件實際上不是一個類型參數。

它只是更容易輸入class Test[T : Manifest]而非class Test[T](implicit evidence: Manifest[T]

+0

我想斯卡拉已經把我寵壞了一下。我最初認爲有很多東西是語法糖,特定於編譯器,最終建立在語言特性的基礎上。這是我最喜歡的關於Scala的東西之一;它的很多設計避免了特殊情況。不幸的是,我不知道你會怎樣設計這個。 +1和**接受**給你。 – KChaloux

2

<-運算符是該語言的保留字(請參見Scala Language Specification,第4頁),但並不是單獨存在。 =>也是一個保留字而不是函數。 (還有_,:,=,<:,<%,>:,#@)。所以你不能用這個名字創建一個函數。我不相信你可以按照你的建議來調整它(也許有人更聰明會知道一種方式)。您可以創建一個名爲`<-`的函數(帶有周圍的反標記),但這可能會比應有的更爲尷尬。

+0

我應該預料到=>是一樣的。只是沒有想過。 +1的有用信息。這是一個遺憾,它是一個編譯器功能,而不是建立在語言功能上。我不知道你會怎麼做,但斯卡拉讓我驚訝於通過簡單的語言構造(例如' - >'來創建元組)的許多事物*看起來像語法糖。 – KChaloux