'"let is unfinished. expect an expression" error. I don't see where though
open System
let highLowGame () =
let rng = new Random();
let secretNumber = rng.Next() % 100 + 1
let rec highLowGameStep () =
printfn "Guess a number: "
let guessStr = Console.ReadLine()
let guess = Int32.Parse(guessStr)
match guess with
| _ when guess > secretNumber -> printfn "Too high!" highLowGameStep ()
| _ when guess = secretNumber -> printfn "You got it!" ()
| _ when guess < secretNumber -> printfn "Too low!" highLowGameStep ()
[<EntryPoint>]
let main argv =
highLowGame ()
0 // return an integer exit code
I know there's tons of these questions and I get that a function in F# must have a return variable. Mine is here | _ when guess = secretNumber -> printfn "You got it!" ()
so I don't understand why it keeps telling me that my block is unfinished
This example is straight out of the F# 3.0 book.
/stdin(14,13): error FS0010: Unexpected identifier in expression. Expected incomplete structured construct at or before this point or other token.
is the full error.
Solution 1:[1]
You have to return something at the end of your let
statement. Otherwise, your function just defines some values, but the expression isn't complete - you're missing a return value. See this MSDN link for more details.
In this case, you can add highLowGameStep ()
at the end to call the function and get its return value:
open System
let highLowGame () =
let rng = new Random();
let secretNumber = rng.Next() % 100 + 1
let rec highLowGameStep () =
printfn "Guess a number: "
let guessStr = Console.ReadLine()
let guess = Int32.Parse(guessStr)
match guess with
| _ when guess > secretNumber -> printfn "Too high!" highLowGameStep ()
| _ when guess = secretNumber -> printfn "You got it!" ()
| _ when guess < secretNumber -> printfn "Too low!" highLowGameStep ()
highLowGameStep ()
[<EntryPoint>]
let main argv =
highLowGame ()
0 // return an integer exit code
Solution 2:[2]
I was getting the same error as OP for a different reason. The reason was improper indentation. Here is my code:
open System
type Temperature = F of int | C of int
[<EntryPoint>]
let main (argv : string[]) =
let freezing = F 32;
Console.WriteLine("A union: {0}", freezing ); //problematic indentation
printfn "A union: %A" freezing ; //problematic indentation
0
I had copy pasted two lines of code (marked as problematic indentation in comments) from a website and it went haywire. It was giving me three different compile time errors at three different lines of code within main
function. When I aligned the indentation of all four statements within main function the issue got resolved:
let main (argv : string[]) =
let freezing = F 32;
Console.WriteLine("A union: {0}", freezing );
printfn "A union: %A" freezing ;
0
I would encourage you to enable View White Space option in Visual Studio IDE while working on F# as mentioned here. Tabs, spaces and code indentation is strongly connected to scoping in F#. Read these posts to gather more understanding around scoping and indentation in F#:
Solution 3:[3]
Roujo has an excellent answer to your question, I'm throwing up another answer to go more in depth into the fundamentals of what's going on.
The key to remember is that everything in F# must be an expression and an expression is something which has a value. That value could be an integer or a float or a function, but it's gotta have a value. The let
isn't, on it's own, an expression; it's a binding of a value to a name so that name can be used in an expression. In your code, you've bound the name highLowGameStep
to a function value, but you don't use that name in an expression. The F# compiler is basically left holding the bag, wondering what expression highLowGameStep
should be used in.
It helps to use the verbose
F# syntax to see what's happening. In verbose
F# the code for your function is (note the in
keyword after each let
binding):
let rng = new Random() in
let secretNumber = rng.Next() % 100 + 1 in
let rec highLowGameStep () =
printfn "Guess a number: "
let guessStr = Console.ReadLine()
let guess = Int32.Parse(guessStr)
match guess with
| _ when guess > secretNumber ->
printfn "Too high!"
highLowGameStep ()
| _ when guess = secretNumber ->
printfn "You got it!"
| _ when guess < secretNumber ->
printfn "Too low!"
highLowGameStep ()
in
In this syntax, it's obvious what's wrong: there's nothing after the last in
where F# expects an expression. (Incidentally, the code in the match
statements wouldn't have executed because there needed to be a line or ;
separating the printfn
function call and the call to highLowGameStep
.)
Quick summary, the let
is binding a name to a value to be used in
an expression. In the code example, there was no expression for the bound name to be used in
and the compiler failed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Roujo |
Solution 2 | |
Solution 3 | egerhard |