我有一个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
File1.fs
module File1
let Run =
let x = 1
printfn "%d" x // this won't print in RELEASE mode
答案 0 :(得分:5)
是的,你是(对)正确 - 它不会打印,因为Run
是一个表达式,似乎编译器正在发布模式中优化它。
为什么不呢?在一个完美的(纯/参考透明)世界中,你有一个unit
类型的表达式,只能有一个值()
...而你甚至不使用或记住这个值!
说实话,我不知道这是一个错误还是一个功能;)
无论如何,这个简单的技巧会帮助你,实际上你不应该像你一样使用带有效果的表达式:
let Run () =
let x = 1
printfn "%d" x
...
File1.Run ()
看 - 现在它是一个函数,并在正确的时间调用,输出又回来了;)
顺便说一句:如果你对这种东西感兴趣,你可以使用像Reflector这样的工具(我目前还没有这个)或者只使用 IL DASM (一个工具VS应该无论如何安装) - 如果你看看编译好的调试/发布程序集,你会注意到这样的事情:IL_001f: call class [FSharp.Core]Microsoft.FSharp.Core.Unit File1::get_Run()
如果您使用表达式,则可以在发行版中找到。
我玩了一下,你必须有创意让编译器做这件事:
例如
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
有效(打印您的1
) - 而
ignore File1.Run
或
let reallyNeed v = ignore v
don`t;) - 似乎你必须实际在某处使用该值:D