2015-12-09 2 views
0

я делаю что-то на самом деле основной неправильно, но я не могу, для жизни меня, выяснить, что это такое ...Выполнение функции с рекурсивной 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#), казалось, получил ответ, но нет.

ответ

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 быть функцией, которая может быть запущена:

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) 

Как правило, если у вас возникли проблемы с пониманием того, что происходит, попробуйте разбить все шаги на отдельные ценности, как это - это облегчает отладку, потому что вы можете evaluat e каждый в свою очередь (в F # Interactive или REPL) и посмотреть, что произойдет!

2

Здесь тест имеет значение unit.

Вы хотите что-то вроде

testItSeveralTimes ((fun _ -> printfn "Running a test"), 2) 

и изменить использования в

test() 
+0

Я изменил его на это: пусть Rec testItSeveralTimes (тест, раз) = printfn "Iterations идти% O" раз время матча с | 0 ->() | _ -> тест() testItSeveralTimes (тест, (раз - 1)) testItSeveralTimes ((FUN _ -> printfn "Запуск теста"), 2) И это работает, но я не знаю, почему. Это потому, что test() заставляет его оцениваться как функция? –

Смежные вопросы