views:

207

answers:

2

Given the following code:

let bar =
    lazy(
        printfn "bar"        
        ())

let foo = 
    lazy(
        printfn "foo"
        bar)

In the interactive window (resetting it each time),

When I call let res = foo.Force () I get:

foo
val res : Lazy<unit> = Value is not created.

When I just call foo.Force() , I get:

foo
bar
val it : Lazy<unit> =
  <ToString exception: Object reference not set to an instance of an object.>
    {IsValueCreated = false;
     Value = null;}

In both cases I would have expected it to just print "foo", however the second case prints "foo\nbar". What's going on here?

+4  A: 

What version of F# do you have? This sounds maybe like a bug that got fixed; when FSI prints a value of type Lazy<'a>, at some point I think the ToString() to display the value used to force the lazy to print it, whereas now it does not.

Brian
It might be, I think my VS2010 beta2 is pretty old: 10.0.21003.1. Does anyone else repro this issue? If not, I'll just assume it's a known issue with a previous versions
RodYan
Yeah, I don't have Beta2 handy, but my internal build at work has the expected behavior, so this seems to have been a bug that got fixed, not sure if the fix had made it into a release yet or not.
Brian
Thanks for verifying
RodYan
I get the above behavior in my beta 2 also.
gradbot
I should also add that "foo.Force() |> ignore" will print "foo" and return type unit
RodYan
A: 

The problem seems to be an implementation detail. How does the Lazy reference know when it has calculated a value? Maybe when it's reference is not ().

Having a type Lazy<unit> doesn't make much sense. Try

let bar =
    lazy(
        printfn "bar"        
        42)
Ray