如果按值调用并按名称调用有效,它们是否都会提供相同的结果? 例如:
import Debug.Trace
trace :: String -> a -> a
foo x y z = y + y + z
z = foo (trace "first" 1)
(trace "second" 2)
(trace "third" 3)
Call-By-Value: "first second third" 7
Call-By-Name: "second second third" 7
Lazy Evaluation: "second third" 7
在这种情况下,我们会得到三种不同的结果,但为什么呢?
答案 0 :(得分:5)
不,你每次都得到相同的结果:7
。
其他消息(“first”等)是由于使用了调试函数Debug.Trace.trace
,该函数用于生成一条消息,该消息准确地公开了表达式被评估。编程执行的“如何”部分通常不被认为是语义的一部分,即结果,而是只考虑返回“什么”。
例如,
的语义let f x = x in f 10 + f 10
是20,与
相同let f x = x in 2 * f 10
但是,如果我们添加痕迹,
let f x = trace "msg" x in f 10 + f 10
因为我们两次调用该函数,所以打印“msg”两次。取而代之的是,
let f x = trace "msg" x in 2 * f 10
只打印一次“msg”。这仅表明评估的方式不同,而不是结果不同。
在正常的“生产”代码中,程序员不应该依赖调试辅助工具(例如Debug.*
模块中的辅助工具来生成消息)。实际上,这会破坏纯函数式编程的许多不错的属性,并且只应用于调试目的。