2011-11-16 55 views
2

我對scala非常陌生,基本上我希望有一些函數與散列表中的字符串耦合。 但是,我在subscribers.get(e.key)(e.EventArgs)處得到一個錯誤;說明選項[EventArgs的=>單位]不帶參數... 示例代碼:如何從Scala中的hashmap調用函數

object Monitor { 
    val subscribers = HashMap.empty[String, (EventArgs) => Unit ] 

    def trigger(e : Event){ 
     subscribers.get(e.key)(e.EventArgs); 

    } 

    def subscribe(key: String, e: (EventArgs) => Unit) { 
     subscribers += key -> e; 
    } 

} 

回答

2

由於get方法返回選項,你可以使用對 '地圖':

subscribers.get(e.key).map(f => f(e.EventArgs)) 

甚至更​​短:

subscribers.get(e.key) map (_(e.EventArgs)) 
+0

在'地圖'上使用地圖是IMO的正確方法。它可以避免模式匹配和NoSuchElementException – AndreasScheinert

1

get只需要一個參數。所以subscribers.get(e.key)返回一個選項,並且您試圖將(e.EventArgs)提供給該選項的apply方法(該方法不存在)。

此外,請嘗試製作subscribers a var(或選擇可變集合類型)。目前你有一個不可變的集合和一個不可變的變量,所以你的地圖不能改變。更地道的方式來聲明這將是

var subscribers = Map[String, EventArgs => Unit]() 
5

一個Mapget方法給你的價值,而不是價值的Option。因此,如果在地圖中找到鑰匙,則獲得Some(value),如果沒有,則獲得None。所以,你需要先「展開」這個選項,以確保居然還有,你可以調用一個函數的值(調用apply上):

def trigger(e: Event): Unit = 
    subscribers.get(e.key).foreach(_.apply(e.EventArgs)) 

def trigger(e: Event): Unit = 
    subscribers.get(e.key) match { 
    case Some(value) => value(e.EventArgs) 
    case None => 
    } 

有很多帖子圍繞着解釋Scala的選項類型。例如this onethis one

另請注意 Luigi關於使用不可變映射(默認Map)而不是var的說法。

+0

謝謝!這裏的所有評論都非常有用! –

0

HashMap.get() Scala的工作方式與Java不同。 get()不是返回值本身,而是返回Option。選項是一種特殊類型,可以有2個值 - Some(x)None。在第一種情況下,它告訴「有一些價值與在地圖中的這樣一個鍵」。在第二種情況下,它告訴「不可以,在地圖中沒有任何東西()」。這樣做是爲了強制程序員檢查map是否實際上有對象,並避免NullPointerException,這在Java代碼中頻繁出現。

所以,你需要的東西是這樣的:

def trigger(e: Event) { 
    val value = subscribers.get(e.key) 
    value match { 
    case None => throw new Exception("Oops, no such subscriber...") 
    case Some(f) => f(e.EventArgs) 
    } 
} 

你可以找到更多信息關於Option類型和模式在斯卡拉here匹配。

+0

你給出的鏈接對它本身並不是很有用。 Bub在那裏引用的鏈接實際上是讓我們在這裏信譽:http://blog.tmorris。net/scalaoption-cheat-sheet/ – AndreasScheinert

+0

@AndreasScheinert:我提供的鏈接不僅僅是關於'Option'類,而是關於整體安全編程,特別是他們爲什麼在HashMap中使用它。所以,不,我不認爲你的鏈接在這個具體的案例中比原來的更有用。 – ffriend

+0

對IMO的程度非常低,作者沒有要求如何使用Option來遠離null。他使用地圖,並且很驚訝他沒有'得到'他所期望的。因此,3個單獨的陳述在這裏看起來很重要:1.您可以獲得選項包裝的值2.您可以獲得(但IMO不應該)3.通過Option上的映射,您可以使用'忽略無'策略。地圖.get值被封裝的鏈接可能會給出解釋。另外我不喜歡這個例子,因爲它將null放在地圖上... – AndreasScheinert