F#:部分应用和预先计算

Ben*_*jol 5 optimization f#

查看今天我的代码中的函数,我想知道是否可以组合部分组合和优化:

let foo (X:float) y1 y2 dx = 
    y1 + (y2 - y1) * dx / X
Run Code Online (Sandbox Code Playgroud)

基本上,只需应用一个比率 - 所以前三个参数在给定的循环中通常是相同的.

我想也许如果我这样做:

let foo2 (X:float) y1 y2 dx = 
    let dy = (y2 - y1) / X
    y1 + dy * dx
Run Code Online (Sandbox Code Playgroud)

当我部分应用前三个参数时,F#会变得聪明并为我优化,但是调试模式似乎并非如此(尽管我不确定我是否以正确的方式测试它).

问题是,这应该有效吗?如果不是有更好的方法(除了用两个参数编写另一个函数)?

Bri*_*ian 4

我认为大多数此类“神奇优化”都需要“效果分析”,而这只能由神话般的“足够智能的编译器”来完成。

思考一下:

let Expensive x y = 
    printfn "I am a side-effect of Expensive"
    x + y  // imagine something expensive

let F x y z =
    let tmp = Expensive x y
    z + tmp

printfn "Least chance of magic compiler optimization"
for i in 1..3 do    
    F 3 4 i

printfn "Slightly better chance"
let Part = F 3 4
for i in 1..3 do    
    Part i

printfn "Now for real"
let F2 x y =
    let tmp = Expensive x y
    (fun z -> z + tmp)

printfn "Of course this still re-does it"
for i in 1..3 do    
    F2 3 4 i

printfn "Of course this finally saves re-do-ing Expensive"
let Opt = F2 3 4
for i in 1..3 do    
    Opt i

(* output

Least chance of magic compiler optimization
I am a side-effect of Expensive
I am a side-effect of Expensive
I am a side-effect of Expensive
Slightly better chance
I am a side-effect of Expensive
I am a side-effect of Expensive
I am a side-effect of Expensive
Now for real
Of course this still re-does it
I am a side-effect of Expensive
I am a side-effect of Expensive
I am a side-effect of Expensive
Of course this finally saves re-do-ing Expensive
I am a side-effect of Expensive

*)    
Run Code Online (Sandbox Code Playgroud)

关键是,有关效果的语言语义要求编译器的行为与此完全相同,除非“昂贵”没有效果,并且编译器非常聪明并且可以自行发现这一点。