【发布时间】:2011-11-01 16:02:18
【问题描述】:
我正在对 Martin Odersky 博士 mentioned over at Skillmatters 的电话簿助记符进行代码审查。
这是他拥有的东西的sn-p:
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。
感谢您抽出宝贵时间。
编辑:
我很确定我已经在 REPL 中正确生成了 val 和函数 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", "$t@r")
words4: List[java.lang.String] = List(hi, Hello world, $t@r)
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 = Coder@119c2af
这是我正在使用的全部代码:
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 似乎不会采用 Map 中没有的任何字符。如果是这种情况,这是否意味着 withDefaultValue 没用?如果是这样,那么我猜呈现的代码有一点缺陷?
【问题讨论】:
-
当我使用
:paste命令将您的“完整代码”粘贴到 REPL 中时,它编译时不会出错。我正在使用 2.9.1.RC3。你能想出一个行为异常的小例子吗? -
添加了一个较小的 sn-p,谢谢。
-
该代码有错误。他在 OSCON 2011 上提交的代码已更正。
-
@Daniel C. Sobral 你是说这个吗? youtube.com/watch?v=3jg1AheF4n0 好像不是在幻灯片中?
-
@mythicalprogrammer 我所知道的是 Martin 承认代码不正确,并说 OSCON 的代码已得到纠正。这就是为什么我不提供答案,只是评论。 :-)
标签: scala