为什么我看不到在主入口点之外调用的printfn的结果(F#)

Sam*_*Sam 0 f#

我有一个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)

Car*_*ten 5

是的,你是(好的)对 - 它不会像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