2017-10-18 110 views
2

我正在致力于一个简单的函数,应该给出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,同时考虑解决方案。我知道应该避免可变变量,这就是我所做的。不幸的是,我担心我在某个地方错过了这个观点,因此我从错误的方面接近了这个问题。

回答

4

您正在引入一个新的q绑定,用于在第一个匹配项中评估的表达式的结果,而不是与其进行比较。你想要的是这样的:

match (y + z * 10) with 
| r when r = q -> (y, z) 
| _ -> aux(y + 1, z + 1, q) 
+0

明白了,谢谢。 – Worice

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,因为它是一个表达式,而不是语句,但它读取更加清晰。

+0

非常感谢您的解释,它帮助我更清晰地理解了这个概念。 – Worice