“let is unfinished. expect an expression” error. I don't see where though

扶醉桌前 提交于 2019-12-12 15:12:58

问题


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.


回答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



回答2:


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.




回答3:


Sharing my experience as I was getting exactly 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 the 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. The moment 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 while working on F# as mentioned here. Tabs and spaces have very strong connection with scoping in F#.



来源:https://stackoverflow.com/questions/35617872/let-is-unfinished-expect-an-expression-error-i-dont-see-where-though

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!