为什么我看不到在主入口点 (F#) 外部调用的 printfn 的结果
Why don't I see results of printfn called outside the main entrypoint (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
File1.fs
module File1
let Run =
let x = 1
printfn "%d" x // this won't print in RELEASE mode
是的,你是(某种)正确的 - 它不会打印,因为 Run
是这里的一个表达式,而且编译器似乎正在发布模式下优化它。
为什么不呢?在一个完美的(pure/referential 透明)世界中,您有一个 unit
类型的表达式,它只能有一个值 ()
...而且您甚至不使用或记住该值!
老实说,我不知道这是错误还是功能 ;)
无论如何,这个简单的技巧 将对您有所帮助,实际上您不应该像您那样使用带有效果的表达式:
let Run () =
let x = 1
printfn "%d" x
...
File1.Run ()
看 - 现在它是一个函数,在正确的时间调用 get,你的输出又回来了 ;)
顺便说一句:如果你对这类东西感兴趣,你要么使用像 Reflector 这样的工具(我现在手边没有),要么只使用 IL DASM (无论如何都应该安装一个工具 VS)——如果你查看编译的 debug/release 程序集,你会注意到没有像这样的东西:
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
不要 ;) - 似乎你必须 实际上 在某处使用该值 :D
我有一个 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
是的,你是(某种)正确的 - 它不会打印,因为 Run
是这里的一个表达式,而且编译器似乎正在发布模式下优化它。
为什么不呢?在一个完美的(pure/referential 透明)世界中,您有一个 unit
类型的表达式,它只能有一个值 ()
...而且您甚至不使用或记住该值!
老实说,我不知道这是错误还是功能 ;)
无论如何,这个简单的技巧 将对您有所帮助,实际上您不应该像您那样使用带有效果的表达式:
let Run () =
let x = 1
printfn "%d" x
...
File1.Run ()
看 - 现在它是一个函数,在正确的时间调用 get,你的输出又回来了 ;)
顺便说一句:如果你对这类东西感兴趣,你要么使用像 Reflector 这样的工具(我现在手边没有),要么只使用 IL DASM (无论如何都应该安装一个工具 VS)——如果你查看编译的 debug/release 程序集,你会注意到没有像这样的东西:
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
不要 ;) - 似乎你必须 实际上 在某处使用该值 :D