Add lazy utility

This commit is contained in:
Michael Miller 2021-01-09 14:19:40 -07:00
parent fb0423ed02
commit 5cac4aa5a1
No known key found for this signature in database
GPG key ID: F9A0C5C65B162436
2 changed files with 25 additions and 10 deletions

View file

@ -1,6 +1,6 @@
require "./abstract_expression" require "./abstract_expression"
require "./label" require "./label"
require "./wrapper" require "./lazy"
module Spectator module Spectator
# Represents a block from a test. # Represents a block from a test.
@ -10,8 +10,7 @@ module Spectator
# or nil if one isn't available. # or nil if one isn't available.
class Block(T) < AbstractExpression class Block(T) < AbstractExpression
# Cached value returned from the block. # Cached value returned from the block.
# Is nil if the block hasn't been called. @value = Lazy(T).new
@wrapper : Wrapper(T)?
# Creates the block expression from a proc. # Creates the block expression from a proc.
# The *proc* will be called to evaluate the value of the expression. # The *proc* will be called to evaluate the value of the expression.
@ -34,13 +33,7 @@ module Spectator
# The block is lazily evaluated and the value retrieved only once. # The block is lazily evaluated and the value retrieved only once.
# Afterwards, the value is cached and returned by successive calls to this method. # Afterwards, the value is cached and returned by successive calls to this method.
def value def value
if (wrapper = @wrapper) @value.get { call }
wrapper.value
else
call.tap do |value|
@wrapper = Wrapper.new(value)
end
end
end end
# Evaluates the block and returns the value from it. # Evaluates the block and returns the value from it.

22
src/spectator/lazy.cr Normal file
View file

@ -0,0 +1,22 @@
require "./wrapper"
module Spectator
# Lazily stores a value.
struct Lazy(T)
@wrapper : Wrapper(T)?
# Retrieves the value, if it was previously fetched.
# On the first invocation of this method, it will yield.
# The block should return the value to store.
# Subsequent calls will return the same value and not yield.
def get(&block : -> T)
if (wrapper = @wrapper)
wrapper.value
else
yield.tap do |value|
@wrapper = Wrapper.new(value)
end
end
end
end
end