我有一个F#控制台应用程序,它调用其他模块中的函数来从主函数入口点执行其工作.我有一系列printfn这些其他功能,为我提供有关程序运行的信息.
在DEBUG模式下编译时,所有语句都会打印到控制台.但是,在RELEASE模式下编译时,打印到控制台的唯一语句是直接位于主入口点函数内的语句.
如何在这些其他模块中打印信息语句?
下面提供了一个代码示例:
Program.fs
[<EntryPoint>]
let main argv =
printfn "%s" "start" // prints in RELEASE and DEBUG mode
File1.Run
printfn "%s" "end" // prints in RELEASE and DEBUG mode
System.Console.ReadLine() |> ignore
0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)
File1.fs
module File1
let Run =
let x = 1
printfn "%d" x // this won't print in RELEASE mode
Run Code Online (Sandbox Code Playgroud)
是的,你是(好的)对 - 它不会像Run这里的表达式一样打印,似乎编译器在发布模式下对它进行优化.
为什么不呢?在一个完美的(纯/参考透明)世界中,你有一个unit只能有一个值的类型表达式()......你甚至不使用或记住这个值!
说实话,我不知道这是一个错误还是一个功能;)
无论如何,这个简单的技巧将帮助你,实际上你不应该像你做的那样使用带有效果的表达式:
let Run () =
let x = 1
printfn "%d" x
...
File1.Run ()
Run Code Online (Sandbox Code Playgroud)
看 - 现在它是一个函数,并在正确的时间调用,你的输出又回来了;)
顺便说一句:如果你对这种东西感兴趣,你可以使用像Reflector这样的工具(目前我手头没有)或者只使用IL DASM(VS应该安装的工具) - 如果你看一下编译的话你会发现调试/发布程序集无处可能:
IL_001f: call class [FSharp.Core]Microsoft.FSharp.Core.Unit File1::get_Run()
Run Code Online (Sandbox Code Playgroud)
如果使用表达式,则可以在发行版中找到.
我玩了一下,你必须有创意让编译器做这件事:
例如
let reallyNeed v =
if v = ()
[<EntryPoint>]
let main argv =
printfn "%s" "start" // prints in RELEASE and DEBUG mode
File1.Run |> reallyNeed
printfn "%s" "end" // prints in RELEASE and DEBUG mode
System.Console.ReadLine () |> ignore
0 // return an integer exit code
Run Code Online (Sandbox Code Playgroud)
工作(打印你的1) - 同时
ignore File1.Run
Run Code Online (Sandbox Code Playgroud)
要么
let reallyNeed v = ignore v
Run Code Online (Sandbox Code Playgroud)
don`t;) - 似乎你必须在某处实际使用该值:D