lazy()适用于单个字符串,但不适用于一系列对象?

时间:2014-01-11 17:52:40

标签: f# lazy-evaluation mutable

所以我有一个单一值的缓存系统,其类型如下:

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

这很有效。

然而,当我尝试对其他东西(一系列对象)做同样的事情时,似乎永远不会保留该值,每次我请求时都会评估它,为什么?以下代码:

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

1 个答案:

答案 0 :(得分:1)

好的,我刚才意识到了原因:lazy()thingy返回的类型。如果它是一个序列,它将始终被评估,因为它不是一个可以存储的正确对象。

我必须将其更改为此才能使其正常工作:

// 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)
      })
)