Currently reading a series of blogposts on F#, targeted at the C# programmer. Right now I've finished reading part 3 ( http://www.jelovic.com/weblog/?p=220 ) and am left puzzled.
The difference between
let readLine = Console.ReadLine ()
and
let readLine () = Console.ReadLine ()
is clear enough but why is there the need to specify the two braces - () - in the following line:
let print (text : string) () = Console.WriteLine text
Shouldn't the compiler be able to figure out you're declaring a delegate print by omitting the braces, so it would look as follows:
let print (text : string) = Console.WriteLine text
Also, the following line made little sense to me
Usually when you have a function that takes parameters of a different type the compiler can differentiate between a function call and a delegate reference, but for unit you have to force it.
Does this mean that when the parameters are different it is safe for the compiler to assume it's a function call?
thank you all for the answers, it's clear to me now. As for the quote, we'll let it rest.
Introduction. I think it's useful to first discuss the difference in the simple example as it helps to understand what "unit" value is. The first declaration creates a string value (and immediately calls ReadLine
to obtain the input from the user):
> let readLine = Console.ReadLine ();;
val readLine : string
The second declaration creates a function that takes unit value as an argument. The function doesn't need to take any input, but we want to define it as a function, so that it can be executed repeatedly (we need that, because the function has side-effect - it reads input from the user).
The "unit" parameter is just a way of creating a function that takes something as argument. "Unit" has only a single value written as ()
, so it doesn't represent any information - just the fact that there is some parameter:
> let readLine () = Console.ReadLine ();;
val readLine : unit -> string
Your question. To look at your example with additional braces. This creates a function that takes a string as the first parameter and takes additional "unit" value as the second parameter. You can see that from the type signature:
> let print (text : string) () = Console.WriteLine text
val print : string -> unit -> unit
This is valid F# declaration, but it is not very useful. It means that the function will be only called when you give it some string to print and also additional "unit" value. You can call it like this:
print "Hello" ()
Even without the additional "unit" parameter, it would be a function (as opposed to a value), so adding the additional parameter doesn't help (you're always creating a function that can be called to print different strings).
There are still cases where this declaration can be interesting. For example, you can call the function just with the string as a parameter. In this case, you'll get a function as the result. The returned function will take unit and will print the string:
let f = print "Hello" // doesn't print anything
f () // prints "Hello"
f () // prints "Hello" again!
So, the compiler allows you to use "unit" values as any other values in the language. This includes uses that may look a bit unfamiliar (and not very useful) at first, but can make a good sense in some scenario.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With