2011-03-27 67 views
4

我有這段Scala代碼定義了一個排序並將其應用於TreeSet。這部分編譯得很好。如何在不重複自己的情況下爲Scala分配TreeSet訂單

val acctOrdering = new Ordering[Account] { 
    def compare(acc1: Account, acc2: Account) { 

    // code to compare based on various criteria 

    } 
} 

private var accountSet = new TreeSet[Account]()(acctOrdering) 

在其他地方的代碼,我想在一組的第一個元素(以及後來的拿到後續的,如果第一個不生產我想要的東西,但通常不會是必要的) ,根據我先前指定的順序。我想下面的工作,但它並沒有編譯:

val firstAccount = accountSet.min 

的錯誤是"could not find implicit value for parameter cmp: Ordering[Account]"

但是,如果我要求的最低時再指定排序對象,它編譯:

val firstAccount = accountSet.min(acctOrdering) 

我認爲它會自動使用我在施工時給出的順序,並且隨着我添加到集合中而逐漸排序,所以在調用min時我不必再次指定順序。

我在做什麼錯?我需要在某處明確定義一個隱式函數嗎?

回答

10

發生什麼事情是,你假設min取決於該集的排序,但它不。具體來說,minmax是幾乎任何集合都可用的通用方法,它們採用隱含的Ordering參數。

但是,如果您嘗試firstKeylastKey,這是SortedSet特定的方法,它們將工作而不必傳遞任何隱式。你可能已經造成

編輯

一個問題是你如何確保你的Account類型可以期待一個Ordering任何方法進行排序。你可以通過把一個隱含的定義Account的對象伴侶裏面,像這樣:

object Account { 
    implicit val ord = new Ordering[Account] { 
    def compare(ac1: Account, acc2: Account): Int = { 
     // code to compare based on various criteria 
    } 
    } 
} 

一旦你這樣做,你就不會需要明確地傳遞順序。

+0

謝謝。將'min'改爲'firstKey'可以編譯它。 min有兩個版本,一個不帶參數,另一個帶有隱式。爲了我的理解,如何使用'def min:A'方法? – Gigatron 2011-03-27 22:24:57

+0

好了,現在我想我明白了......看起來無參數的'min'在TreeSet上永遠不可用,因爲在沒有參數的情況下調用它總是會返回到需要隱式參數的min版本。 – Gigatron 2011-03-27 23:34:21

+0

@Gigatron只有一個'min'定義。您在ScalaDoc上看到的另一個定義被標記爲「_use case_」。這意味着這不是真正的簽名,而是代表大多數時間發生的「假」簽名。在這種情況下,不帶任何參數調用'min'將在大多數情況下工作。 – 2011-03-28 14:18:11

相關問題