我想使用模式匹配而不是if-else
语句重写递归函数,但是我得到(正确的)警告消息,代码的某些部分是无法访问的。事实上,我的逻辑评估错误。
我想重写的功能是:
def pascal(c: Int, r: Int): Int =
if (c == 0)
1
else if (c == r)
1
else
pascal(c - 1, r - 1) + pascal(c, r - 1)
此功能按预期工作。我使用模式匹配重写它如下,但现在函数没有按预期工作:
def pascal2 (c : Int, r : Int) : Int = c match {
case 0 => 1
case r => 1
case _ => pascal2(c - 1, r - 1) + pascal2(c, r - 1)
}
我哪里错了?
Main
:
println("Pascal's Triangle")
for (row <- 0 to 10) {
for (col <- 0 to row)
print(pascal(col, row) + " ")
println()
}
答案 0 :(得分:3)
以下陈述&#34;阴影&#34;变量r
:
case r =>
也就是说,&#34; r&#34;事实上,在这种情况下,声明并不是&#34; r&#34;你已经在上面定义了。它是自己的&#34; r&#34;等于&#34; c&#34;因为你告诉Scala将任何值分配给一个名为&#34; r。&#34;
的变量因此,你真正想要的是:
def pascal2(c: Int, r: Int): Int = c match{
case 0 => 1
case _ if c == r => 1
case _ => pascal2(c-1, r-1) + pascal2(c, r-1)
}
但这不是尾递归。
答案 1 :(得分:1)
我完全同意@wheaties并建议你遵循他的指示。为了完整起见,我想指出一些替代方案。
您可以自己编写unapply
:
def pascal(c: Int, r: Int): Int = {
object MatchesBoundary {
def unapply(i: Int) = if (i==0 || i==r) Some(i) else None
}
c match {
case MatchesBoundary(_) => 1
case _ => pascal(c-1, r-1) + pascal(c, r-1)
}
}
我不会声称它在这种情况下提高了可读性。只是想展示组合语义相似case
s(具有相同/相似的案例主体)的可能性,这可能在更复杂的示例中有用。
还有一种可能的解决方案,它利用了Scala的模式匹配语法仅将小写变量视为匹配变量的事实。以下示例显示了我的意思:
def pascal(c: Int, r: Int): Int = {
val BoundaryL = 0
val BoundaryR = r
c match {
case BoundaryL => 1
case BoundaryR => 1
case _ => pascal(c-1, r-1) + pascal(c, r-1)
}
}
由于BoundaryL
和BoundaryR
以大写字母开头,因此不会将它们视为变量,而是直接用作匹配对象。因此上述工作(将它们更改为boundaryL
和boundaryR
时不会,这也会产生编译器警告)。这意味着您只需将r
替换为R
即可让您的示例正常工作。由于这是一个相当丑陋的解决方案,我只是出于教育目的而提及它。