2014-01-10 98 views
2
let eval a b = 
    let r = a + b 
    printf "calculate.." 
    r 
type Foo() = 
    member this.Eval = eval 5 10 
[<EntryPoint>] 
let main argv = 
    let f = Foo() 
    let a = f.Eval 
    let b = f.Eval 
    0 

這將調用eval 2次而不是一次。看起來this.Eval是一個函數指針,每次調用.Eval時調用eval。F#中的成員變量

我真正想要的是一個變量。

我做這個解決它......

let eval a b = 
    let r = a + b 
    printf "calculate.." 
    r 
type Foo() = 
    let e = eval 5 10 
    member this.Eval = e 
[<EntryPoint>] 
let main argv = 
    let f = Foo() 
    let a = f.Eval 
    let b = f.Eval 
    0 

這是這樣做的,如果我只是想有一個成員變量,而不是方法的正確方法是什麼?

+0

你第一個方法解決了第二個問題?你想要完成什麼?不同的是,第一種方法是運行時評估,而第二種方法是編譯時,因爲'e'是在編譯時評估的。 – MadeOfAir

+0

我只想將this.Eval作爲一個變量,我可以在對象構造中分配一個值。 正如你所說,第一種方法是運行時評估,但我只想一次評估結果(eval 5 10)。 –

+1

我認爲第二種解決方案是好的,但我會把這個放在課堂上 –

回答

2

您描述的行爲是.NET屬性始終工作的方式,無論是在C#還是F#中。每次讀取該物業時,都會評估該物業的主體。

除了你的解決方案,這是正確的,我補充說它計算Foo構建時的值。你可能只想當你閱讀的財產在第一時間要計算的值,如果是這樣,你可以使用Lazy做到這一點:

let eval a b = 
    let r = a + b 
    printf "calculate.." 
    r 
type Foo() = 
    // a lazy computation that will be evaluated the first time .Value is called 
    let e = lazy eval 5 10 
    member this.Eval = e.Value 
[<EntryPoint>] 
let main argv = 
    let f = Foo() 
    let a = f.Eval 
    let b = f.Eval 
    0 
2

我覺得越idimatic F#風格將是:

type Foo() = 
    let eval a b = 
     let r = a + b 
     printf "calculate.." 
     r 
    let e = eval 5 10 
    member this.Eval = e 
[<EntryPoint>] 
let main argv = 
    let f = Foo() 
    let a = f.Eval 
    let b = f.Eval 
    0 

即你把類中的eval與一個let綁定來隱藏實現