首页 > 解决方案 > 如何在 F# 中使用匹配表达式移动光标位置?

问题描述

我认为在 F# 中使用匹配表达式比使用 while 循环和 if 语句更有意义,但我无法让它工作。代码对我来说看起来不错,我没有收到任何错误。有人可以解释为什么它不起作用吗?

open System

let width  = Console.WindowWidth
let height = Console.WindowHeight

let rec main() =
    let x = Console.CursorLeft
    let y = Console.CursorTop
    match Console.ReadKey().Key with
    | ConsoleKey.UpArrow    -> Console.SetCursorPosition(x, (y - 1))
    | ConsoleKey.RightArrow -> Console.SetCursorPosition((x + 1), y)
    | ConsoleKey.DownArrow  -> Console.SetCursorPosition(x, (y + 1))
    | ConsoleKey.LeftArrow  -> Console.SetCursorPosition((x - 1), y)
    | _ -> main()
    main()

Console.ReadKey() |> ignore

标签: f#expressionmatch

解决方案


您遇到的问题是,在定义main()函数之后,您永远不会调用它。

这是您的代码现在的样子:

let rec main() =
    // The definition of main()

Console.ReadKey() |> ignore

请记住,在 F# 中,缩进很重要:在let someName =声明之后,下一个缩进块的其余部分是函数的主体。因此,您的代码中只有两个顶级表达式:一个定义一个main()从未调用过的函数,另一个从控制台读取密钥。在 F# 中,命名函数没有什么特别之处main()。要将函数作为程序的入口点(程序运行时要运行的第一件事),您需要使用EntryPoint属性声明它:

[<EntryPoint>]
let rec main() =
    // The definition of main()

还要注意文档关于隐式入口点的说法:

当程序没有EntryPoint明确指示入口点的属性时,将使用要编译的最后一个文件中的顶级绑定作为入口点。

您向我们展示的程序中的“顶级绑定”做了两件事:定义一个函数,然后读取一个键。

EntryPoint属性放在您的let rec main() =行之前,我怀疑这会解决您的问题。或者,如果您将其作为.fsx脚本运行,那么[<EntryPoint>]这不是正确的方法,而是需要main()在程序的顶层部分调用 to(在它被定义之后)。


推荐阅读