我最近选择了F#,目前正在使用命令行实用程序来帮助自动完成一些与工作相关的任务。我已经为我的不同命令选项实现了一个命令解析器和一个Union,一切正常。
当我根据选项进入执行部分时,似乎有些东西会破坏。
假设我有一个模块,其中包含两个我希望运行的函数,具体取决于命令输入的结果
module OptionRunner
let option1 a b = a + b
let option2 c d = c |> Seq.map(fun i-> i + d)
现在,我的判断器将如下所示:
let runCommands =
if option.opt1 then
option1
else if options.opt2 then
option2
这可能过于简化,但希望能够公平地理解我想要实现的目标。
现在,我的问题是,无论我在runCommands中做什么,以及我在OptionRunner模块中有多少不同的函数,它总是调用option1
,然后继续遍历该模块中的整个函数列表。
我甚至尝试为每个函数创建本地模块来测试它。它仍然总是叫做option1。
我无法看到我的缩进或模块结构与此文件之间的区别与项目中的任何其他模块(没有问题)
有没有人经历过并解决了这个问题?这让我疯了。
答案 0 :(得分:0)
如果不查看实际代码,很难看出出了什么问题。这种行为的最常见原因是您实际上定义的是unit
值,而不是可以调用的函数。例如,如果你有类似的东西:
module Demo
let foo =
printfn "foo"
let bar =
printfn "bar"
let run =
if false then foo
elif false then bar
else ()
这里,foo
和bar
实际上是在初始化模块时评估的值(因此程序总是运行它们的主体和打印" foo"和&#34 ;栏&#34)。 run
中的代码实际上并不是调用函数,它只是引用已经评估的值。
要将它们转换为函数,您必须添加一些参数:
let foo () =
printfn "foo"
let bar () =
printfn "bar"
let run () =
if false then foo ()
elif false then bar ()
else ()
在您的实际示例中,看起来您实际上是在定义函数(定义是正确的),但您的调用代码看起来只是指代值。所以我怀疑问题是我所描述的更复杂的版本。
答案 1 :(得分:0)
在F#中,执行顺序实际上非常简单,它是自上而下从左到右。因此,完全可以预期,您的模块"运行"。方式,你如何控制评估是通过使事情变得懒惰或适当的功能......例如。如果你说
let sum = a + b
评估sum
并根据a
和b
设置它。如果你不希望在那里定义总和,你定义它,你可能宁愿写一些像
let sum a b = a + b
您必须知道上方sum
是单个值。它就像一个局部变量。
较低的sum
是一个带有两个参数的函数。但是,在这两种情况下,sum
都会被评估,只是第二个是"完成"当你的功能被定义时。
因此,在查看原始问题时,您很可能需要将option1
作为一个以单位值()
作为输入的函数。并将其称为option1()
。