knocte
knocte

Reputation: 17939

lazy() works for single string but not for a sequence of objects?

So I have a cache system for a single value with a type like this:

module CachedSessionToken = 

// returns a lazy value that initializes the cache when 
// accessed for the first time (safely)
let private createCacheInitialization() = 
    lazy(SomeLongRunningOperationThatReturnsAString())

// current cache represented as lazy value
let mutable private currentCache = createCacheInitialization()

// Reset - cache will be re-initialized next time it is accessed
// (this doesn't actually initialize a cache - just creates a lazy value)
let Reset() = currentCache <- createCacheInitialization()

let GetCache() =
    currentCache.Value

And this works.

However, when I try to do the same for something else (a sequence of objects), it seems that the value is never retained, it's all the time evaluated every time I request it, why? The code below:

module CachedLayout = 

let mutable private lastAccess:Option<DateTime> = None

// returns a lazy value that initializes the cache when 
// accessed for the first time (safely)
let private createCacheInitialization() = 
  lazy(
      seq {
        yield new SomeObject (".")
        yield new SomeObject ("..")

        let folderPaths = SomeLongRunningOperationThatReturnsArrayOfStrings()
        lastAccess <- Option.Some(DateTime.Now)
        for name in folderPaths
          do yield new SomeObject (name)

        let filePaths = SomeOtherLongRunningOperationThatReturnsArrayOfStrings()
        lastAccess <- Option.Some(DateTime.Now)
        for name in filePaths
          do yield new SomeObject (name)
      }
  )

// current cache represented as lazy value
let mutable private currentCache = createCacheInitialization()

// Reset - cache will be re-initialized next time it is accessed
// (this doesn't actually initialize a cache - just creates a lazy value)
let Reset() = currentCache <- createCacheInitialization()

let GetCache() =
    if (lastAccess.IsSome && DateTime.Now > (lastAccess.Value + TimeSpan.FromSeconds (10.0))) then
        Reset()
    currentCache.Value

Upvotes: 0

Views: 73

Answers (1)

knocte
knocte

Reputation: 17939

Ok, I just realised why: the type that the lazy() thingy returns. If it's a sequence, it will be always evaluated because it's not a proper object that can be stored.

I had to change it to this to make it work:

// returns a lazy value that initializes the cache when 
// accessed for the first time (safely)
let private createCacheInitialization() = 
  lazy(
      new List<SomeObject>(seq {
          yield new SomeObject (".")
          yield new SomeObject ("..")

          let folderPaths = SomeLongRunningOperationThatReturnsArrayOfStrings()
          lastAccess <- Option.Some(DateTime.Now)
          for name in folderPaths
              do yield new SomeObject (name)

          let filePaths = SomeOtherLongRunningOperationThatReturnsArrayOfStrings()
          lastAccess <- Option.Some(DateTime.Now)
          for name in filePaths
              do yield new SomeObject (name)
      })
)

Upvotes: 1

Related Questions