sas*_*ang 7 f# functional-programming
在 F# 中,如果我写
let p = printfn "something"
Run Code Online (Sandbox Code Playgroud)
它将对表达式求值一次。任何后续引用都p将计算为单位。从理论的角度来看,函数的定义,这是有道理的。函数应该只对相同的输入返回相同的结果。
但是,如果我希望发生副作用(即输出到屏幕),那么我需要将参数传递给 p。通常这个参数就是unit值。
let p () = printfn "something"
Run Code Online (Sandbox Code Playgroud)
但是,当每次应用函数的参数都相同时,为什么 F# 每次都会对函数求值呢?当然,与第一种情况相同的推理应该适用吗?函数的输入p不会改变,因此不需要多次评估它。
Mar*_*ann 14
严格来说,动作printfn不是函数。特别是,它不是一个纯函数,因为它不是引用透明的。这是可能的,因为 F# 不是严格的函数式语言(它是“函数式优先”语言)。它没有明确区分纯函数和不纯动作。
printfn "something"的返回值为()( unit),表示p与单位值 绑定()。打印在屏幕上的事实something是计算表达式的副作用。
F# 是一种备受期待的语言。这就是为什么您会在屏幕上看到打印作为绑定到something的副作用。一旦表达式被求值,就仅绑定到- 值。printfn "something"pp()
F# 不会记忆函数调用,因此当您更改p为函数时,每次使用(). 由于所有函数都可能是不纯的,因此编译器无法判断记忆化是否合适,因此它不会这样做。
其他语言以不同的方式做到这一点。例如,Haskell 是惰性评估的,并且还明确区分纯函数和不纯操作,因此它可以在此类情况下应用不同的优化。