2010-06-09 3 views
4

я проверить некоторые простые F # код для «если» выражение, но результат является неожиданным для меня:«если» выражение вопрос

> let test c a b = if c then a else b;; 
val test : bool -> 'a -> 'a -> 'a 

Однако

> test true (printfn "a") (printfn "b");; 
a 
b 
val it : unit =() 

Я бы ожидать только « »напечатано, но здесь я получил оба« a »и« b ». Интересно, почему так получается? Благодаря!

+0

Спасибо за ваши ответы! Взяв оценку перед вызовом, я бы хотел, чтобы результат был получен как «a, b, a», то есть добавление результата вызова в конец. Ладно, не суть. Вероятно, именно так работает F #. – Here

ответ

6

Возможно, потому что вызовы функций printfn оцениваются до того, как когда-либо возникнет тестовый вызов? Если вы хотите, чтобы оба вызова функций были отложены до тех пор, пока они не будут использованы, вы можете захотеть lazy computation или макросы (которых нет у F #).

7

Hao является правильным. Вы должны обернуть эти выражения в функции, чтобы сделать их ленивыми. Попробуй это.

let test c a b = if c then a() else b();; 
test true (fun() -> printfn "a") (fun() -> printfn "b");; 
4

Чтобы быть совершенно ясно, что это по той же причине, что

let f x = x + 1 
f (3+5) 

оценивает (3+5) перед вызовом f. Практически каждый язык, кроме Haskell, работает так (по модулю языков с макросами).

0

Вот ленивая версия для вычислений. F #, кажется, требует аннотации типа, чтобы использовать здесь метод Force. Немного беспорядочно, но он работает.

> let test c a b = if c then (a:Lazy<unit>).Force else (b:Lazy<unit>).Force;; 
val test : bool -> Lazy<unit> -> Lazy<unit> -> (unit -> unit) 

> test true (lazy (printfn "a")) (lazy (printfn "b"))();; 
a 
val it : unit =() 
> 
Смежные вопросы