2017-01-30 429 views
2

閱讀我有了一個例子功能的控制檯應用程序行:功能與在其他數據文件

let aFxUsedFromTheEntryPoint() = 
    let aHelperFx (cThing) (iThing) (qThing) = 
     Unchecked.defaultof<Quote> 

    let c = 
     thisFx() //this line reads in and process lots of data; takes some time 

    let i = 
     thatFx() //this line also reads in and processes lots of data; takes some time 

    aList 
    |> List.map (fun q -> aHelperFx c i q) 

如何在函數中使用的ci變量?他們在最後兩行之前是否只讀過一次,並且只是反覆使用,然而長aList是?或者他們在'aList'中每q執行一次?

如果是後者,有沒有更好的方法去編寫這樣的函數?我可以以某種方式編寫函數,使ci只運行一次,但通過了很多次,但必須在aList

+1

這也許是最常見的F#初學者問題;看到答案[這裏](http://stackoverflow.com/questions/41049285/when-are-f-function-calls-evaluated-lazily-or-immediately/41049323#41049323)。 – TeaDrivenDev

+3

爲什麼人們再次低估完全有效的問題,甚至不說爲什麼? – TeaDrivenDev

+0

我的猜測是他們的論點是我應該使用搜索框。雖然,我甚至沒有想到F#會被急切地評估,除非另有說明(或者在'Sequence'上),因此'c'和'i'應該一次讀入內存,然後重複使用。這意味着爲了節省時間,我需要查看實際功能中的其他位置。感謝鏈接@TeaDrivenDev。 – Steven

回答

2

最明顯的解決方案是將它們移出函數體:

let c = thisFx() //this line reads in and process lots of data; takes some time 
let i = thatFx() //this line also reads in and processes lots of data; takes some time 

let aFxUsedFromTheEntryPoint() = 
    let aHelperFx (cThing) (iThing) (qThing) = Unchecked.defaultof<Quote> 
    aList |> List.map (fun q -> aHelperFx c i q) 

通常,如果你的功能的模塊內聲明的,那麼這兩個let綁定可以在同一級別上聲明作爲功​​能,在這種情況下在模塊層面。

這是我會考慮的第一件事。現在,如果您希望在第一次調用aFxUsedFromTheEntryPoint函數時調用它們,那麼您可以使用其他技術,如memoization或惰性值,如其他答案中所述,但請注意,第一次調用該函數將比後續更慢調用。

1

也許包裝成lazy會有幫助嗎?

let x4 = lazy (
      printfn "%A" "Long Running stuff" 
      let addX (x:int) = x + 1 
      addX) 
//val x4 : Lazy<(int -> int)> = Value is not created. 
let c = x4.Force() 4 
//"Long Running stuff" 
//val c : int = 5 
c // val it : int = 5 
c