Singletone implementation
-
Wednesday, July 18, 2012 5:00 PM
Hi, F# people!
Please advice, I've found that kind of Singleton implementation in F# somewhere on msdn
type Singleton private() = static let instance = new Singleton() static member Instance = instanceAnd it's pretty good. (Clear and just 2 lines)
But what do you think of this idea
type Singleton2 private() = static member Instance = lazy(new Singleton2())
I mean to use lazy evaluation here but don't quite understand how to make it work?
========================
And another question:
type NameCollection = { Name : string SecName : string } [<Sealed>] type Singleton private() = static let instance = new Singleton() static member Instance = instance member public this.UsefulPartExample = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |] let m = Singleton.Instance
//And I thought that next line should have changed the 'instance' property but it didn't m.UsefulPartExample.[0] <- {Name = "Ivy"; SecName = "Red"}
(* FSI output is the same
val it : NameCollection [] =
[|{Name = "Pam";
SecName = "Pamovich";}; {Name = "Sam";
SecName = "Fisher";}|] *)What should i write to make 'NameCollection' changeable? Thanks in advance.
All Replies
-
Wednesday, July 18, 2012 5:25 PM
Your implementation of this.UsefulPartExample property returns freshly created array every time someone access it.
To make it changeable you have to implement internal array value:
[<Sealed>] type Singleton private() = let upa = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |] static let instance = new Singleton() static member Instance = instance member public this.UsefulPartExample = upanow you can change internal array via property:
m.UsefulPartExample.[0] <- {Name = "Ivy"; SecName = "Red"}Petr
-
Wednesday, July 18, 2012 5:35 PM
To implement lazy creation you can do this way, for example:
[<Sealed>] type Singleton private() = let upa = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |] do printfn "Creating" static let instance = lazy(new Singleton()) static member Instance = instance.Force() member public this.UsefulPartExample = upa let m = Singleton.Instance let m1 = Singleton.InstanceAs per MSDN (http://msdn.microsoft.com/en-us/library/dd233247.aspx) Force() will be called only once. You can see it if you'll access Instance property several times. Printout "Creating" will appear only once.Petr
-
Wednesday, July 18, 2012 7:20 PMModerator
Properties are evaluated each time they are accessed, so you'll be creating a new lazy instance each time you access your property. Note that F# 3.0 includes an auto-property feature which you could use like this:
type Singleton private() = static member val Instance = new Singleton()With this feature, the right hand side is evaluated only once. You could also use lazy on the right hand side if you wanted to, though this only makes sense if there is some significant initialization cost that you'd like to delay. -
Wednesday, July 18, 2012 10:06 PMModerator(to be very clear, 'Force' is called each time you access the property, but lazy.Force() only does work the first time, and just returns the cached value for each subsequent call)
Brian McNamara [MSFT]
-
Thursday, July 19, 2012 7:49 AM
Thanks everyone for your answers! But why it's so strange with the initialization? I mean
So, why it isn't working without internal array, what are mechanisms beyound that?[<Sealed>] type Singleton private() =
//It's not obvious for me, why it's neccessary to create a binding first, and let upa = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |] static let instance = new Singleton() static member Instance = instance
//...only then pass the value here so that property became changeable member public this.UsefulPartExample = upa
-
Thursday, July 19, 2012 12:18 PM
Your initial implementation of the property:
member public this.UsefulPartExample = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |]created a new instance of an array with the same records every time you call this member. It was roughly equal to:
member public this.UsefulPartExample = new NameCollection[] {...}But let binding (let upa = ...) happens in the class constructor because it placed before any member declaration. It occurs only once and member this.UsefulPartExample returns this object which you can perform operations on. In this case identifier 'upa' is an internal field of the class.
Also you can test that your initial member implementation creates new array this way:
[<Sealed>] type Singleton private() = do printfn "Creating" static let instance = lazy(new Singleton()) static member Instance = instance.Force() member public this.UsefulPartExample = [| {Name = "Pam"; SecName = "Pamovich"} {Name = "Sam"; SecName = "Fisher"} |] let m = Singleton.Instance let arr1 = m.UsefulPartExample // arr1 is freshly created with 'Pam' and 'Sam' arr1.[0] <- {Name = "Ivy"; SecName = "Red"} let arr2 = m.UsefulPartExample // arr2 is another freshly created array with 'Pam' and 'Sam' arr2.[0] <- {Name = "John"; SecName = "Doe"}
Petr
- Edited by Plepilov Thursday, July 19, 2012 12:29 PM
- Marked As Answer by SmartWizard Thursday, July 19, 2012 1:27 PM
-
Thursday, July 19, 2012 1:27 PMThank you, Petr! Now I understand.
- Edited by SmartWizard Thursday, July 19, 2012 1:28 PM

