2011-08-23 57 views
0

我正在做一個代碼審查電話簿助記符馬丁Odersky博士mentioned over at Skillmatters似乎無法使用默認值工作

這裏是什麼,他有一個片段:

class Coder(words: List[String]) { 

    private val mnemonics = Map(
    '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", 
    '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") 

    /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9'*/ 
    private val charCode: Map[Char, Char] = 
    for ((digit, str) <- mnemonics; letter <- str) yield (letter -> digit) 


    /** Maps a word to the digit string it can represent */ 
    private def wordCode(word: String): String = word.toUpperCase map charCode 

    /** A map from digit strings to the words that represent them, 
    * e,g. 5282 -> Set(Java, Kata, Lava, ...) */ 

    private val wordsForNum: Map[String, List[String]] = 
    (words groupBy wordCode) withDefaultValue List() 

我試圖聲明一切,函數和變量怎麼看withDefaultValue的行爲,這是我得到了什麼:

scala> val words3 = List("moo", "1111") 
words3: List[java.lang.String] = List(moo, 1111) 

scala> (words3 groupBy wordCode) withDefaultValue List() 
java.util.NoSuchElementException: key not found: $ 
    at scala.collection.MapLike$class.default(MapLike.scala:224) 

在他正在談論的視頻如果單詞未被映射,那麼我們應該得到一個項目列表(這從視頻中的17分鐘開始)。我收到一個錯誤?我正在使用Scala的REPL 2.9.0.1。

謝謝你的時間。

編輯:

我敢肯定,我已經產生的VAL和REPL DEF正常工作。

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

val mnemonics = Map(
    '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", 
    '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") 

// Exiting paste mode, now interpreting. 

mnemonics: scala.collection.immutable.Map[Char,java.lang.String] = Map(8 -> TUV, 4 -> GHI, 9 -> WXYZ, 5 -> JKL, 6 -> MNO, 2 -> ABC, 7 -> PQRS, 3 -> DEF) 

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

val charCode: Map[Char, Char] = 
    for ((digit, str) <- mnemonics; letter <- str) yield (letter -> digit) 

// Exiting paste mode, now interpreting. 

charCode: Map[Char,Char] = Map(E -> 3, X -> 9, N -> 6, T -> 8, Y -> 9, J -> 5, U -> 8, F -> 3, A -> 2, M -> 6, I -> 4, G -> 4, V -> 8, Q -> 7, L -> 5, B -> 2, P -> 7, C -> 2, H -> 4, W -> 9, K -> 5, R -> 7, O -> 6, D -> 3, Z -> 9, S -> 7) 

def wordCode(word: String): String = word.toUpperCase map charCode 

wordCode: (word: String)String 

我也嘗試在REPL中定義整個類。

defined class Coder 

scala> val words4 = List("hi", "Hello world", "[email protected]") 
words4: List[java.lang.String] = List(hi, Hello world, [email protected]) 

scala> var listPhoneNumber = new Coder(words4) 
java.util.NoSuchElementException: key not found: 
    at scala.collection.MapLike$class.default(MapLike.scala:224) 

scala> val words5 = List("hi","hello","ciao") 
words5: List[java.lang.String] = List(hi, hello, ciao) 

scala> var listPhoneNumber = new Coder(words5) 
listPhoneNumber: Coder = [email protected] 

這裏是整個代碼我使用:

class Coder(words: List[String]) { 



    private val mnemonics = Map(

    '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", 

    '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") 



    /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9'*/ 

    private val charCode: Map[Char, Char] = 

    for ((digit, str) <- mnemonics; letter <- str) yield (letter -> digit) 



    /** Maps a word to the digit string it can represent */ 

    private def wordCode(word: String): String = word.toUpperCase map charCode 



    /** A map from digit strings to the words that represent them, 

    * e,g. 5282 -> Set(Java, Kata, Lava, ...) */ 

    private val wordsForNum: Map[String, List[String]] = 

    (words groupBy wordCode) withDefaultValue List() 



    /** Return all ways to encode a number as a list of words */ 

    def encode(number: String): Set[List[String]] = 

    if (number.isEmpty) 

     Set(List()) 

    else { 

     for { 

     splitPoint <- 1 to number.length 

     word <- wordsForNum(number take splitPoint) 

     rest <- encode(number drop splitPoint) 

     } yield word :: rest 

    }.toSet 



    /** Maps a number to a list of all word phrases that can represent it */ 

    def translate(number: String): Set[String] = encode(number) map (_ mkString " ") 

} 

EDIT2 - 小片段:

val mnemonics = Map(
    '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", 
    '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") 

    val charCode: Map[Char, Char] = 
    for ((digit, str) <- mnemonics; letter <- str) yield (letter -> digit) 

    def wordCode(word: String): String = word.toUpperCase map charCode 

    val words = List("Hello", "1111") // doesn't work 

    (words groupBy wordCode) withDefaultValue List() 

    val words2 = List("Hello", "Odersky") 

    (words2 groupBy wordCode) withDefaultValue List() //works 

我剛剛注意到它好像方法/函數wordCode不會採用任何不在地圖中的字符。如果是這種情況,這是否意味着withDefaultValue是無用的?如果是這樣,那麼我認爲提出的代碼有一點缺陷?

+1

當我用':paste'命令將你的「整個代碼」粘貼到REPL中時,它編譯時沒有錯誤。我正在使用2.9.1.RC3。你可以試着想出一個行爲意外的小例子嗎? –

+0

添加了一個較小的片段,謝謝。 – mythicalprogrammer

+1

該代碼有錯誤。他在OSCON 2011上展示的代碼已更正。 –

回答

3

你最後的通知是正確的:只要一個字符不在地圖中,函數wordCodemap charCode部分將失敗,並拋出異常。因此你不會到達wihDefaultPart

如果存在缺陷,則取決於您期望角色不在地圖中時的行爲。