Reputation: 876
If I declare a method with no parameters and then call it (in F#-interactive), then I get the expected behaviour: "test" is displayed on screen.
let somefn() =
printfn "test"
>
val somefn : unit -> unit
> somefn();;
test
val it : unit = ()
However, If I declare the method without parentheses, then I get some different behavior:
let somefn =
printfn "test"
>
test
val somefn : unit = ()
> somefn;;
val it : unit = ()
> somefn();;
somefn();;
^^^^^^
C:\...\Local\Temp\stdin(4,1): error FS0003: This value is not a function and cannot be applied.
So what I don't understand:
Upvotes: 2
Views: 256
Reputation: 10624
The comments above answer this question but I'll add some detail.
When you define a function, each parameter is actually a pattern match with only one case. For example you could write:
let somefn 0 = 1
The type of this function is int -> int
. The first parameter is inferred to be an int
, but this generates a warning because there are other ints that are not being matched on. somefn 0
returns 1
, but somefn 1
throws an exception "The match cases were incomplete"
.
The type unit
has only one value: ()
. It's effectively as a "nothing" value for the input or an output of a function. It has a pattern match that looks exactly like the value (just like []
for an empty list), which is why you can add a unit parameter to any function using ()
. These functions are all exactly the same:
let somefn () = ()
let somefn (x:unit) = ()
let somefn (_:unit) = ()
When you write a function that doesn't take any parameters, you just add a single unit
parameter so that it's a function and not a value, and therefore you delay its execution. Just to drive the point home, you could even add more than one unit
parameter, although you would never need to do this:
let somefn () () = ()
// unit -> unit -> unit
Upvotes: 7