F# 对象表达式中的可变状态
我希望 F# 对象表达式具有可变状态。 第一种方法是使用引用单元格,如下所示:
type PP =
abstract member A : int
let foo =
let a = ref 0
{ new PP with
member x.A =
let ret = !a
a := !a + 1
ret
}
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
另一种方法如下:
type State(s : int) =
let mutable intState = s
member x.state
with get () = intState
and set v = intState <- v
[<AbstractClass>]
type PPP(state : State) =
abstract member A : int
member x.state
with get () = state.state
and set v = state.state <- v
let bar n =
{ new PPP(State(n)) with
member x.A =
let ret = x.state
x.state <- ret + 1
ret
}
let barA1 = bar 0
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
哪个版本可能性能更好(我需要状态更新 x.state <- ret + 1 在性能关键部分)?我的猜测是 State 对象也分配在堆上,因此没有理由第二个版本应该更快。然而,它使用起来稍微更有吸引力。
感谢您的任何反馈和建议
I would like to have a mutable state in an F# object expression.
The first approach is to use ref cells as follows:
type PP =
abstract member A : int
let foo =
let a = ref 0
{ new PP with
member x.A =
let ret = !a
a := !a + 1
ret
}
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
A different approach would be as follows:
type State(s : int) =
let mutable intState = s
member x.state
with get () = intState
and set v = intState <- v
[<AbstractClass>]
type PPP(state : State) =
abstract member A : int
member x.state
with get () = state.state
and set v = state.state <- v
let bar n =
{ new PPP(State(n)) with
member x.A =
let ret = x.state
x.state <- ret + 1
ret
}
let barA1 = bar 0
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
Which version would be likely more performing (I need the state updating x.state <- ret + 1
in performance critical sections)? My guess is that the State object is also allocated on the heap so there is no reason why the second version should be faster. However it is slightly more appealing to use.
Thanks for any feedback and suggestions
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如 Daniel 所说,最后一种方法本质上等同于使用内置的 ref 。
使用
ref
时,您将分配两个对象 - 您要返回的对象和引用单元格本身。您可以通过使用具体实现将其减少为单个分配的对象(但我认为这在实践中并不重要):此外,您正在使用只读属性来修改对象的内部状态并返回新状态每次。这是一种危险的模式,可能会非常令人困惑 - 带 getter 的属性不应修改状态,因此您可能应该使用方法 (
unit -> int
)。As Daniel said, the last approach is essentially equivalent to using built-in
ref
.When using
ref
, you're allocating two objects - the one that you're returning and the reference cell itself. You can reduce this to just a single allocated object by using a concrete implementation (but I don't think this will matter in practice):Aside, you are using read-only property that modifies internal state of the object and returns a new state each time. This is a dangerous pattern that could be quite confusing - properties with getter shouldn't modify the state, so you should probably use a method (
unit -> int
) instead.您的
State
类与ref
相同。它们都是引用类型(您无法从对象表达式捕获可变值类型)。如果可能的话,我更喜欢内置类型。ref
是表示堆分配的可变值的惯用方式。如果对性能有疑问,请对其进行基准测试。
Your
State
class is identical toref
. They're both reference types (you can't capture a mutable value type from an object expression). I would prefer a built-in type when possible.ref
is the idiomatic way to represent a heap-allocated mutable value.If ever in doubt about performance, benchmark it.