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.
是完整错误。
答案 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#中的作用域有很强的联系。