我正在开发一个简单的函数,在给定x
的情况下,应返回一个元组(y, z)
,使y <= abs(5) + z * 10 = x
,其中z
为最小可能值。
在C中,我会遍历z++
和y++
,直到他们的总和与x
匹配。
目前,我正试图在功能上解决这个问题。请考虑以下示例:
let foo x =
let rec aux (y, z, q) =
match (y + z * 10) with
q -> (y, z)
|_ -> aux(y + 1, z + 1, q) //How to correctly set the increments?
aux(0, 0, x)
无论如何,此方法始终返回(0, 0)
。在提出解决方案时,我提到了this question。我知道应该避免使用可变变量,这就是我所做的。不幸的是,我恐怕在某个地方错过了这一点,因此我从错误的一方接近问题。
答案 0 :(得分:4)
您正在为第一个案例匹配中评估的表达式的结果引入新的q
绑定,而不是与之进行比较。你想要的是这样的:
match (y + z * 10) with
| r when r = q -> (y, z)
| _ -> aux(y + 1, z + 1, q)
答案 1 :(得分:1)
在F#中,您通常在值表达式或模式匹配表达式中。当你这样做时:
match (y + z * 10) with
q -> (y, z)
您实际上是在说:“计算y + z * 10
,然后始终将结果分配给新变量q
,忽略此新变量并返回(y, z)
”。这是因为q
写在模式匹配表达式中,因为它位于with
之后。
这也是为什么你在下一行收到警告“这条规则永远不会匹配”的原因。当人们学习F#时,这是一个非常普遍的误解。
当你这样做时,你根本就没有真正使用模式匹配。所以我建议改为使用if
表达式:
if y + z * 10 = q
then (y, z)
else aux (y + 1, z + 1, q)
这实际上相当于在C中使用三元运算符?
和:
,因为它是一个表达式,而不是一个语句,但它读得更清楚。