2014-01-10 2 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

Я думаю, что второе решение в порядке, но я бы поставил let внутри класса –

ответ

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 внутри класса с позволением связывания, чтобы скрыть реализация

Смежные вопросы