功能数字恢复

时间:2017-10-31 09:45:20

标签: f#

在C中,我会用循环解决问题。代表这个想法,例如:

void foo(int x){
    while(x > 0){
        printf("%d", x % 10);
        x /= 10;
    }
}

使用F#,我无法使函数返回单个值。我试过了:

let reverse = 
    let aux =
        fun x -> 
            x % 10
    let rec aux2 =
        fun x -> 
            if x = 0 then 0
            else aux2(aux(x / 10))
    aux2 n

但它始终返回基本案例0

我无法超越这种方法,其中递归结果通过操作维护,并且不能单独报告(根据可能的理解):

let reverse2 =
    let rec aux =
        fun x -> 
            if x = 0 then 0
            else (x % 10) + aux (x / 10)     // The operation  returning the result
    aux n

这是我正在做的一个简单的练习,以便"功能化"我脑海。因此,我正在寻找一种不涉及库函数的方法来解决这个问题。

1 个答案:

答案 0 :(得分:6)

更改可变变量值的for循环可以重写为递归函数。您可以将可变变量视为函数的隐式参数。因此,如果我们有一个可变变量x,我们需要明确地将新状态x作为函数参数传递。与C函数最接近的等效函数是递归F#函数:

let rec foo x =
    if x > 0 then
        printf "%d" (x % 10)
        foo (x / 10)

这本身并不是特别有用,因为它返回unit并且只有副作用。您可以使用其他参数收集每个循环的结果。这通常称为累加器:

let foo x =
    let rec loop x acc =
        if x > 0 then
            loop (x / 10) (x % 10 :: acc)
        else acc

    loop x [] |> List.rev

foo 100  // [0; 0; 1]

我创建了一个内部loop函数,它实际上是递归函数。外部foo函数从内部循环开始,[]作为累加器。在每次迭代期间,项目被添加到列表的开头,并且累加器列表在结束时反转。

您可以使用其他类型作为累加器,例如一个字符串,并附加到字符串而不是将项添加到列表中。