功能增量

时间:2017-10-18 09:53:07

标签: f#

我正在开发一个简单的函数,在给定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。我知道应该避免使用可变变量,这就是我所做的。不幸的是,我恐怕在某个地方错过了这一点,因此我从错误的一方接近问题。

2 个答案:

答案 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中使用三元运算符?:,因为它是一个表达式,而不是一个语句,但它读得更清楚。