2

This is probably something simple, but I have a .fs file with a simple sample function.

let printHello = printfn "%A" "Hello"

I have set the search path to the .fs file using

>#I "PathToMyFSFile"

I have loaded my file using

>#load "Test.fs"

Which worked fine. Now I want to call the function which actually prints the hello to screen, but thats turning out to be too difficult

> Test.printHello;;
val it : unit = ()

Tried Test.printHello();; as well but doesn't work. How do I actually make it print "Hello" to screen?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Chaitanya
  • 5,203
  • 8
  • 36
  • 61

3 Answers3

6

your current printHello isn't actually a function. To make it a function you need to do

let printHello() = printfn "%A" "Hello"

noice the (). Then everything should work.

EDIT:

When the compiler sees your definition

let printHello = printfn "%A" "Hello"

it passes it as a simple data term. For example, consider this program:

let printHello = printfn "%A" "Hello"
printfn "World"
printHello

This will print "Hello" then "World". printHello just has unit type, so does nothing. Compare it to

let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()

Here printHello is a function. In this case, the function is only executed when it is explicitly called, so this prints "World" then "Hello".

John Palmer
  • 25,356
  • 3
  • 48
  • 67
  • So what did I end up declaring printHello as anyway then? isn't it a partial/curried function that I can pass around or execute later when I am ready? How do I do that? – Chaitanya Nov 11 '11 at 09:51
  • The interactive window is telling you exactly what it is - a value of the unit type `()`. My version is what you can pass around as a function. I will add some more explaination in the answer – John Palmer Nov 11 '11 at 10:10
5

As John already said, your printHello isn't a function - it is a value of type unit. When you give printfn all the required arguments (as you did), it does the imperative operation and return unit (which is a type with only a single value written as ()). You can see that writing that declaration does the printing immediately:

> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()

When you use printHello later, it simply refers to this unit value (which does not carry any information).

If you want to make it a function (of type unit -> unit) that will do something each time it is executed, then you can use the sample that John posted.

The function printfn was not partially applied, because you gave it all the parameters it required (so it could just print immediately). If you wanted to use partial application, you could use something like:

> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit

Now printHello is a function that waits for the second parameter and then runs:

> printHello "World";;
Hello World
val it : unit = ()

> printHello "F#";;
Hello F#
val it : unit = ()
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Your explanation around currying made the penny drop. Didn't realise that by passing all the parameters, I was executing it immediately and hence ending up with the 'result' of the function rather than the function itself. – Chaitanya Nov 11 '11 at 14:57
1

As has already been said in other answers, "printHello" set to () is unit, the return value of printfn is () , console print is side-effect.

use Lazy:

let printHello = Lazy (fun () ->printfn "%A" "Hello")

DEMO

> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once

use Seq:

let printHello = seq { printfn "%A" "Hello"; yield ()}

DEMO

> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • Your syntax for creating lazy values seems wrong. It should be either `Lazy.Create (fun () -> printfn "Hello")` (using a function) or it should be `lazy printfn "Hello"` using language feature. – Tomas Petricek Nov 11 '11 at 11:56