I couldn't find this glancing through the language spec, but below is some code that answers it, with a comment from Don that I dug up from an old email.

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

(*
F# immutable values (functions, tuples, immutable records, immutable 
discriminated union cases) have no guaranteed behaviour w.r.t. object reference 
equality, and the behaviour of this construct is under-specified and may change 
under different optimization settings. That's just how it will always be.

To get object identity you can use a delegate value, or wrap the function in an 
object that carries a stamp, or wrap the function value in a reference cell or 
object.
*)

let f x = x + 1
printfn "%d" (f 3)
printfn "%A" (f = f)  // false

type Int2Int = delegate of int -> int
let fdel = Int2Int(f)
printfn "%d" (fdel.Invoke(3))
printfn "%A" (fdel = fdel)  // true
By on 9/2/2008 3:58 PM ()

Thanks for the response. I think I like the ref suggestion better for my needs, but I can't get it to work either!!

type api =
static member private op (a:string) (b:string) (c:string) =
printf "calling op with %A %A %A\n" a b c
static member Op = ref api.op;;

printf "api: %A\n" (api.Op = api.Op);; // false ??

type api2() =
member private x.op (a:string) (b:string) (c:string) =
printf "calling op with %A %A %A\n" a b c
member x.Op = ref x.op;;
let API = new api2();;

printf "api2: %A\n" (API.Op = API.Op);; // false ??

By on 9/2/2008 5:22 PM ()

The confusion here is just about when member evaluation happens. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
type WhenAreMembersEvaluated() =
    static member Foo = 
        printfn "Hi"
        0
    member this.Bar = 
        printfn "Hi"
        0

printfn "%d" WhenAreMembersEvaluated.Foo  // Hi 0
printfn "%d" WhenAreMembersEvaluated.Foo  // Hi 0  (note: Hi again)
let wame = new WhenAreMembersEvaluated()
printfn "%d" wame.Bar  // Hi 0
printfn "%d" wame.Bar  // Hi 0  (note: Hi again)

Thus in your code, you're calling 'ref' twice, so of course they are different 'ref' objects.

To get what you want, introduce a 'let':

1
2
3
4
5
6
7
type api() =
    static let ApiOp = ref api.op  // evaluates only once
    static member private op (a:string) (b:string) (c:string) = 
        printf "calling op with %A %A %A\n" a b c
    static member Op = ApiOp

printf "api: %A\n" (api.Op = api.Op) // true

Hope that helps!

By on 9/2/2008 5:41 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