When you define a method using "member", its content is computed every time you access it. Here, you're creating a new lazy value each time.

Use a "let" to define a local value (that will be evaluated only during the constructor).

By on 12/8/2009 10:18 AM ()

Well, my actual code is a discriminated union type. Such a type allows members, but apparently not let declarations ("This declaration element is not permitted in an augmentation"). I don't suppose there's any way around that?

By on 12/8/2009 10:54 AM ()

Sure, you can "add" let bindings by defining a module of the same name as the type, then tagging it ModuleSuffix:

1
2
3
4
5
6
7
8
 

type DU = | DU

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module DU = 
    let x = 1

If you want to expose members instead of let bindings (or if you want instance members on your DU), you can do this:

1
2
3
4
5
6
7
8
9
 

type DU = | DU 
    with
    member x.X = DUStatics.X
and internal DUStatics() = 
    static let x = 1
    static member X = x
By on 12/8/2009 1:13 PM ()

Michael, I don't think either of these do what the original asker wants though (my read is that he wants each instance to carry around a lazy object that can change state).

There's no way to 'add extra state' to instances of a DU without exposing it as part of the data carried by the DU.

By on 12/8/2009 1:51 PM ()

Michael, I don't think either of these do what the original asker wants though (my read is that he wants each instance to carry around a lazy object that can change state).

There's no way to 'add extra state' to instances of a DU without exposing it as part of the data carried by the DU.

Oh, my mistake then. If that's the case then the problem is the same as it is anywhere else in .NET when you want to add on information to an arbitrary object. I suppose some sort of dictionary holding a weakreference to the original object and the additional information could work, assuming performance isn't important. Then access could be done with normal members.

By on 12/9/2009 5:43 PM ()

my read is that he wants each instance to carry around a lazy object that can change state

That's correct.

There's no way to 'add extra state' to instances of a DU without exposing it as part of the data carried by the DU.

I really don't know what this means. Does it mean there's no way to add a lazy member to a DU?

By on 12/8/2009 2:02 PM ()

You can only do it by e.g. doing what's done in the second example below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 

type MyDU =
    | Num of int
    member this.X =
        match this with
        | Num(x) -> x

let x1 = Num 1        
printfn "%d" x1.X 
printfn "%d" x1.X 

type MyLazyDU =
    | LNum of Lazy<int>
    member this.X =
        match this with
        | LNum(x) -> x.Force()

let x2 = LNum(lazy(printfn "calculate..."; 1))
printfn "%d" x2.X 
printfn "%d" x2.X 

Does it make sense?

By on 12/8/2009 2:19 PM ()

Yes, thanks.

By on 12/8/2009 2:27 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper