Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this definition returns a function?

Tags:

f#

I found the following in the book Expert F# 4.0, Fourth Edition, by Don Syme, Adam Granicz, and Antonio Cisternino:

let generateStamp =
    let mutable count = 0
    (fun () -> count <- count + 1; count)

I could not understand why this code creates a function:

val generateStamp : (unit -> int)

It looks to me like its signature should be

val generateStamp : int

For example, the following code:

let gS =
    let mutable count = 0
    (printfn "%d" count; count)

creates an int value:

val gS : int = 0

As I understand it the code (fun () -> count <- count + 1; count) should first evaluate the lambda and then count. So the value of generateStamp should be just count, as it is in the definition of gS. What am I missing?

like image 258
Soldalma Avatar asked Aug 03 '26 05:08

Soldalma


1 Answers

In any block of F# code, the last expression in that block will be the value of that block. A block can be defined in one of two ways: by indentation, or with ; between the block's expressions.

The expression fun () -> other expressions here creates a function. Since that's the last expression in the code block under let generateStamp =, that's the value that gets stored in generateStamp.

Your confusion is that you think that the expressions inside the fun () are going to be evaluated immediately as part of the value of generateStamp, but they're not. They are defining the body of the anonymous function returned by the fun () expression. You're absolutely right that inside that block of code, count is the last expression and so it's the thing returned by that function. But the fun () expression creates a function, which will only evaluate its contents later when it is called. It does not evaluate its contents immediately.

By contrast, the expression (printfn "%d" count; count) is a block of code with two expressions in it. It is not a function, so it will be immediately evaluated. Its last expression is count, so the value of the code block (printfn "%d" count; count) is count. Since the (printfn "%d" count; count) block is being evaluated immediately, you can mentally replace it with count. And so the value of gS is count, whereas the value of generateStamp is a function that will return count when it's evaluated.

like image 200
rmunn Avatar answered Aug 06 '26 10:08

rmunn