冗余模式匹配
Redundant Pattern Matching
我正在尝试编写一个函数来查找给定数字 n
是否为完全平方数。这是我的尝试:
local
fun perfect_square_iter x z = let val sqr = z * z in
case (x,z) of
(sqr,_) => true
| (_, 0) => false
| _ => perfect_square_iter x (z - 1)
end
in fun perfect_square n = perfect_square_iter n n
end
现在,当我尝试使用 sml myfile.sml
运行 时,出现以下错误:
lab03.sml:17.5-20.43 Error: match redundant
(sqr,_) => ...
--> (_,0) => ...
--> _ => ...
/usr/lib/smlnj/bin/sml: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/FLINT/trans/translate.sml:1735.13-1735.21
这对我来说似乎不是一个多余的模式,因为它只匹配两个常量,然后匹配其他任何东西。为什么编译器认为这是多余的?
sqr
不是常量,即使您对它进行了 let 绑定。从句法上讲,它是一个变量,在模式语言中,所有变量都是可以匹配任何内容的自由变量。因此,您的模式 (sqr,_)
匹配所有参数。逗号前的值将绑定到该子句正文中的 sqr
(=>
的 RHS),从而隐藏您对 z*z 的绑定,它之后的值将是丢弃。这涵盖了所有可能的情况,因此您的其余匹配是多余的。
您可以通过考虑以下(绝对糟糕的)代码来验证模式中的变量匹配是否引入了新的局部作用域:
fun f xs =
let val x = 5 in
case xs of
[] => 0
| x::xs => x
end;
它编译,但是然后,例如 f [1,7,10]
returns 1 而不是 5。
对于您的代码,您需要使用 if ... then ... else
而不是模式匹配来处理 x = sqr
的情况。像
(_,0) => false
| (_,_) => if x = sqr ...
(这是假设您仍然想使用模式匹配,但是由于您不能按照您想要的方式使用它,因此可以对代码进行更彻底的重组,例如免除 let
可能合适)。
我正在尝试编写一个函数来查找给定数字 n
是否为完全平方数。这是我的尝试:
local
fun perfect_square_iter x z = let val sqr = z * z in
case (x,z) of
(sqr,_) => true
| (_, 0) => false
| _ => perfect_square_iter x (z - 1)
end
in fun perfect_square n = perfect_square_iter n n
end
现在,当我尝试使用 sml myfile.sml
运行 时,出现以下错误:
lab03.sml:17.5-20.43 Error: match redundant
(sqr,_) => ...
--> (_,0) => ...
--> _ => ...
/usr/lib/smlnj/bin/sml: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/FLINT/trans/translate.sml:1735.13-1735.21
这对我来说似乎不是一个多余的模式,因为它只匹配两个常量,然后匹配其他任何东西。为什么编译器认为这是多余的?
sqr
不是常量,即使您对它进行了 let 绑定。从句法上讲,它是一个变量,在模式语言中,所有变量都是可以匹配任何内容的自由变量。因此,您的模式 (sqr,_)
匹配所有参数。逗号前的值将绑定到该子句正文中的 sqr
(=>
的 RHS),从而隐藏您对 z*z 的绑定,它之后的值将是丢弃。这涵盖了所有可能的情况,因此您的其余匹配是多余的。
您可以通过考虑以下(绝对糟糕的)代码来验证模式中的变量匹配是否引入了新的局部作用域:
fun f xs =
let val x = 5 in
case xs of
[] => 0
| x::xs => x
end;
它编译,但是然后,例如 f [1,7,10]
returns 1 而不是 5。
对于您的代码,您需要使用 if ... then ... else
而不是模式匹配来处理 x = sqr
的情况。像
(_,0) => false
| (_,_) => if x = sqr ...
(这是假设您仍然想使用模式匹配,但是由于您不能按照您想要的方式使用它,因此可以对代码进行更彻底的重组,例如免除 let
可能合适)。