这个'let'之后的块未完成。期待一个表达

时间:2010-05-09 10:43:27

标签: f#

大家好我正在用F#做一个项目但是当我使用let num = line代替以下代码时我得到了这个错误。我是F#的新手,所以我无法解决问题。我的代码应该做这件事。用户输入一个数字并计算斐波纳契,但如果用户输入的数字不是抛出异常

open System
let rec fib n = 
match n with
|0->0
|1->1
|2->1
|n->fib(n-1)+fib(n-2);;

let printFibonacci list = 
for i=0 to (List.length list)-1 do
printf "%d " (list.Item(i));;


let control = true
while control do 
    try
    printfn "Enter a Number:" 

    let num:int = Convert.ToInt32(stdin.ReadLine()) 

    with
        | :? System.FormatException->printfn "Number Format Exception";
    let listFibonacci = [for i in 0 .. num-1->fib(i)]
    printFibonacci(listFibonacci)
    printfn "\n%A"(listFibonacci)
    control<-false

Console.ReadKey(true)
exit 0;;

2 个答案:

答案 0 :(得分:8)

我不是F#专家,但我发现您发布的代码存在3个问题。

1)正如Lasse V Karlsen评论的那样 - f#使用'越位'规则,因此你的'fib'表达式需要缩进主体。如果你在Visual Studio Shell中运行它,它应该通过蓝色警告你在适当的代码下的波浪线。

2)'control'和'num'都是可变值,因此需要明确声明 f#是一种函数式语言,因此默认情况下,任何表达式都是不可变的,即它们在声明后不允许更改状态。

在f#中,说'let n = expr'并不意味着'将expr的值赋给n',就像你说c#或c ++一样。相反,它意味着'从根本上说 expr'并且将永远像一个数学方程式。

因此,如果你想更新变量的值,你可以使用特殊的'&lt; - '表示法,它相当于'将rhs上的值赋给lhs',你需要将该变量声明为可变的,即'这个值可以在以后更改'

所以我认为num和control都需要在循环的顶部声明为

let mutable control = false  
let mutable num = 0 // or whatever you want the initial value of num to be

作为附注,您不必将num显式声明为int(如果需要,可以使用),但f#将推断出类型

答案 1 :(得分:3)

如果我正确理解您的代码,您需要继续询问输入数字n,直到给出有效数字并将fibonacci数字打印到n。在这种情况下,您最好在try块内移动计算和打印。这是一个带格式的更新版本。

open System
let rec fib n = 
    match n with
    |0->0
    |1->1
    |2->1
    |n->fib(n-1)+fib(n-2);;

let printFibonacci list = 
    for i=0 to (List.length list)-1 do
        printf "%d " (list.Item(i))

let mutable control = true //you forgot to add the 'mutable' keyword
while control do 
    try
        printfn "Enter a Number:" 

        let num:int = Convert.ToInt32(stdin.ReadLine()) 

        let listFibonacci = [for i in 0 .. num-1 -> fib(i)] 
        printFibonacci(listFibonacci)
        printfn "\n%A"(listFibonacci)
        control <- false

    with
        | :? System.FormatException -> printfn "Number Format Exception"

//add the ignore statement to drop the resulting ConsoleKeyInfo struct    
//or the compiler will complain about an unused value floating around.      
Console.ReadKey(true) |> ignore 

// exit 0 (* Exit isn't necessary *)

除了使用命令式样式号输入例程并依赖控件流的异常外,还可以使用递归的getNumberFromConsole函数:

open System
let rec fib n = 
    match n with
    | 0 -> 0
    | 1 | 2 -> 1
    | n -> fib(n-1) + fib(n-2);;

let printFibonacci list = 
    for i=0 to (List.length list)-1 do
        printf "%d " (list.Item(i))

//alternative number input, using recursion
let rec getNumberFromConsole() =
    match Int32.TryParse(stdin.ReadLine()) with
    | (true, value) -> value
    | (false, _) -> printfn "Please enter a valid number"
                    getNumberFromConsole() 

printfn "Enter a Number:" 
let num = getNumberFromConsole()
let listFibonacci = [for i in 0 .. num-1 -> fib(i)] 
printFibonacci(listFibonacci)
printfn "\n%A"(listFibonacci)

Console.ReadKey(true) |> ignore 

P.S。谢谢你给我看stdin。我从来不知道它存在。现在我可以编写一些交互式脚本。