使用递归F#运行函数

时间:2015-12-09 20:53:45

标签: f#

我正在做一些非常基本的错误,但我不能,因为我的生活,弄清楚它是什么......

    let rec testItSeveralTimes (test, times) =
        printfn "Iterations to go %O" times
        match times with
            | 0 -> ()
            | _ -> 
                test
                testItSeveralTimes (test, (times - 1))

     testItSeveralTimes ((printfn "Running a test"), 2)

我的期望是:

Iterations to go 2
Running a test
Iterations to go 1
Running a test
Iterations to go 0
Running a test
val it : unit = ()

我得到的是:

Running a test
Iterations to go 2
Iterations to go 1
Iterations to go 0
val it : unit = ()

似乎函数在开始时被评估一次,然后被忽略。

这个问题(Wrapping a function with an indeterminate number of parameters in F#)似乎有答案,但没有。

2 个答案:

答案 0 :(得分:5)

如果将test参数提取到单独的步骤中, 问题变得很明显:

let test = printfn "Running a test"
// expression has run and printed already!
// value of "test" is a simple value (unit) now
testItSeveralTimes (test, 2)

作为评估let test =表达式的一部分,printfn 函数立即运行

然后,test被赋予值(),这是printfn的输出

testItSeveralTimes内,test的值就在那里,但没有 做任何事。

正如约翰所说,你需要让test参数成为可以运行的函数:

let rec testItSeveralTimes (test, times) =
    printfn "Iterations to go %O" times
    match times with
        | 0 -> ()
        | _ -> 
            test()  // test parameter is now a function
            testItSeveralTimes (test, (times - 1))

通过此更改,您还需要将test值定义为函数 没有立即运行:

let test() = printfn "Running a test"
// value of test is a function and is not run yet
testItSeveralTimes (test, 2)

作为一般规则,如果您在理解正在发生的事情时遇到问题,请尝试将所有步骤分解为单独的值 - 这样可以更容易调试,因为您可以依次评估每个步骤(在F#Interactive中)或REPL)看看会发生什么!

答案 1 :(得分:2)

此处test的值为unit

你想要像

这样的东西
testItSeveralTimes ((fun _ -> printfn "Running a test"), 2)

并将使用情况更改为

test()