Scala match匹配顺序疑问:Cons分支为何不可达且sum恒为0?
Scala自定义List的sum方法中Cons分支不可达、始终返回0的问题解决
你的问题根本不是case分支顺序的问题,而是Scala模式匹配的标识符解析规则导致的:
在Scala中,模式匹配里的小写字母开头的标识符会被当作变量绑定——也就是说,你写的case mNil =>其实是把传入的任何mList实例都绑定到名为mNil的变量上,后面的case Cons(h, t)自然就永远不会被执行,所以不管你传入什么列表,sum方法都会直接返回0,IDEA也会提示Cons分支不可达。
而书中的Nil是大写开头的case object,所以case Nil =>会正确匹配对应的空列表对象,不会被当作变量。
解决方法有两种,选一种就行:
方法一:遵循Scala命名规范,把空列表对象改成大写开头(推荐)
把case object mNil改成case object MNil,然后在match和apply方法里统一使用MNil:
sealed trait mList[+A] case object MNil extends mList[Nothing] case class Cons[+A] (head:A, tail:mList[A]) extends mList[A] object mList { def sum(ints: mList[Int] ): Int = ints match { case MNil => 0 case Cons(h, t) => h + sum(t) } def apply[A](as: A*): mList[A] = if (as.isEmpty) MNil else Cons(as.head, apply(as.tail:_*)) }
方法二:保留小写名称,用反引号包裹标识符
如果不想改名,就在match分支里用反引号把mNil包起来,告诉Scala这是一个已有的常量对象,不是要绑定的变量:
sealed trait mList[+A] case object mNil extends mList[Nothing] case class Cons[+A] (head:A, tail:mList[A]) extends mList[A] object mList { def sum(ints: mList[Int] ): Int = ints match { case `mNil` => 0 case Cons(h, t) => h + sum(t) } def apply[A](as: A*): mList[A] = if (as.isEmpty) mNil else Cons(as.head, apply(as.tail:_*)) }
两种方法都能解决你的问题,不需要调换case分支的顺序。
内容的提问来源于stack exchange,提问作者Moeda Chaos
相关产品推荐
相关产品推荐

