“让未完成。期待表达”错误。我不知道在哪里

时间:2016-02-25 03:47:36

标签: f#

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

我知道有很多这些问题,我知道F#中的函数必须有一个返回变量。我在这里| _ when guess = secretNumber -> printfn "You got it!" ()所以我不明白为什么它一直告诉我我的块未完成

这个例子直接来自F#3.0书。

/stdin(14,13): error FS0010: Unexpected identifier in expression. Expected incomplete structured construct at or before this point or other token.

是完整错误。

3 个答案:

答案 0 :(得分:3)

您必须在let声明的最后返回一些内容。否则,您的函数只定义了一些值,但表达式并不完整 - 您错过了返回值。 See this MSDN link for more details.

在这种情况下,您可以在末尾添加highLowGameStep ()来调用函数并获取其返回值:

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

答案 1 :(得分:2)

Roujo对你的问题有一个很好的答案,我会提出另一个答案,更深入地了解正在发生的事情的基本原理。

要记住的关键是F#中的所有内容都必须是表达式,而表达式才是值。该值可以是整数或浮点数或函数,但它必须具有值。 let不是它自己的表达式;它是一个值与名称的绑定,以便可以在表达式中使用该名称。在您的代码中,您已将名称highLowGameStep绑定到函数值,但您不能在表达式中使用该名称。 F#编译器基本上保留了包,想知道应该使用什么表达式highLowGameStep

使用verbose F#语法查看发生的情况很有帮助。在verbose F#中,您的函数代码是(注意每个in绑定后的let关键字):

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

在这种语法中,显而易见的是:在F#期望表达式的最后in之后没有任何内容。 (顺便提一下,match语句中的代码不会被执行,因为需要一行或;printfn函数调用和highLowGameStep调用分开}。)

快速摘要,let将名称绑定到要使用的值in表达式。在代码示例中,没有表达式要使用绑定名称in并且编译器失败。

答案 2 :(得分:2)

分享我的经验,因为我得到了与OP完全相同的错误,原因不同。原因是缩进不当。这是我的代码:

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

我从网站上复制了两行代码(在评论中标记为problematic indentation)并且它变得混乱了。它在main函数内的三个不同代码行给出了三个不同的编译时错误。在我将主函数中所有四个语句的缩进对齐的那一刻,问题得到了解决:

let main (argv : string[]) = 
     let freezing = F 32;
     Console.WriteLine("A union: {0}", freezing );
     printfn "A union: %A" freezing ;
     0

我建议您在处理F#时按照here启用Visual Studio中的View White Space选项。制表符和空格与F#中的作用域有很强的联系。