F#调用指定模块函数却执行其他模块代码,如何正确调用?
问题:F#模块中调用指定成员却执行了其他模块的代码
现有MyTest.fs代码:
module MyTest module MyModule1 = let f = // thread sleep printfn "hi from module 1" module MyModule2 = let f = printfn "hi from module 2"
Program.fs代码:
// entry point [<EntryPoint>] let main argv = MyTest.MyModule2.f 0
执行dotnet run后输出同时包含两个模块的打印内容,而预期只输出hi from module 2。
原因分析
你这里的let f = printfn ...是值绑定,而非函数定义。F#中模块的顶级值绑定会在模块被加载时自动执行,当你引用MyTest.MyModule2.f时,整个MyTest模块会被加载,连带MyModule1里的f也会被初始化执行,因此两个打印语句都触发了。
解决方法
方法1:将f定义为函数
把f改成需要主动调用才执行的无参函数,修改MyTest.fs:
module MyTest module MyModule1 = let f () = // 添加括号,定义为无参函数 printfn "hi from module 1" module MyModule2 = let f () = printfn "hi from module 2"
在Program.fs中调用函数:
[<EntryPoint>] let main argv = MyTest.MyModule2.f () // 显式调用函数 0
此时只有被调用的MyModule2.f()会执行,MyModule1.f不会自动触发。
方法2:使用延迟加载(Lazy)
如果需要保留值的形式但延迟执行逻辑,可使用lazy关键字:
修改MyTest.fs:
module MyTest module MyModule1 = let f = lazy (printfn "hi from module 1") module MyModule2 = let f = lazy (printfn "hi from module 2")
调用时通过Force()触发执行:
[<EntryPoint>] let main argv = MyTest.MyModule2.f.Force() 0
这样只有被调用Force()的延迟值会执行,另一个不会自动初始化。
内容的提问来源于stack exchange,提问作者Topazus
相关产品推荐
相关产品推荐

