F # - creating delegates

We are currently reading a F # blog series aimed at a C # programmer. Right now I have finished reading part 3 ( http://www.jelovic.com/weblog/?p=220 ) and am left puzzled.

Difference between

let readLine = Console.ReadLine ()

and

let readLine () = Console.ReadLine ()

clear enough, but why you need to specify two curly braces - () - in the following line:

let print (text: string) () = Console.WriteLine text

If the compiler cannot understand that you are declaring the delegate print by omitting the curly braces, it looks like this:

let print (text: string) = text Console.WriteLine

Also, the next line made no sense to me

Usually, when you have a function that accepts parameters of a different type, the compiler can distinguish between a function call and a delegate reference, but for a unit you must force it.

Does this mean that when the parameters are different, is it safe for the compiler to consider it a function call?

Thanks to everyone for the answers, now it’s clear. As for the quote, we will leave it alone.

+4
source share
3 answers

Introduction . It seems to me useful to first discuss the difference in a simple example, as this helps to understand what a "unit" is. The first declaration creates a string value (and immediately calls ReadLine to get input from the user):

 > let readLine = Console.ReadLine ();; val readLine : string 

The second declaration creates a function that takes the value of one as an argument. The function does not require input of any input, but we want to define it as a function so that it can be executed multiple times (we need it because the function has a side effect - it reads input from the user).

The "unit" parameter is just a way to create a function that takes something as an argument. "Unit" has only one value, written as () , therefore it does not represent any information - only the fact that there is some parameter:

 > let readLine () = Console.ReadLine ();; val readLine : unit -> string 

Your question. . Look at your example with extra curly braces. This creates a function that takes the string as the first parameter and takes the additional value "unit" as the second parameter. You can see this from a signature like:

 > let print (text : string) () = Console.WriteLine text val print : string -> unit -> unit 

This is a valid F # declaration, but it is not very useful. This means that the function will be called only when you give it a line to print, as well as the additional value of "one." You can call it like this:

 print "Hello" () 

Even without the additional parameter β€œunit”, it will be a function (as opposed to a value), so adding an additional parameter does not help (you always create a function that can be called to print different lines).

There are still cases where this declaration may be interesting. For example, you can only call a function with a string as a parameter. In this case, you will get the function as the result. The returned function will take a block and print a line:

 let f = print "Hello" // doesn't print anything f () // prints "Hello" f () // prints "Hello" again! 

Thus, the compiler allows you to use the values ​​of "units" like any other values ​​in the language. This includes usage, which may seem a little unfamiliar (and not very useful) at the beginning, but may make sense in some kind of scenario.

+5
source

It:

 let print (text : string) = Console.WriteLine text 

creates a print method as follows:

 print "hi" // prints "hi" in the console 

Where:

 let print (text : string) () = Console.WriteLine text 

creates a method to print a specific line, for example:

 let printHi = print "hi" // Does NOT print a string to the console printHi () // But now this does print "hi" :) printHi () // And this... 

Essentially, this is a "print-specific string X for the console function" factory, which the result (ex printHi) can be reused repeatedly.

+3
source

Using currying,

 let makePrinter (text : string) () = Console.WriteLine text 

allows you to create a function that always prints a specific line, for example

 let helloPrinter = makePrinter "hello" 

gives hi just by calling

 helloPrinter () 

On the other hand,

 let print (text : string) = Console.WriteLine text 

immediately displays "text" if called

 print "hello" 

and returns (), not a function like unit -> unit , as in the first case with curry.

+2
source

All Articles