From 5cac4aa5a184c25fe0f3bf20cabae75ddc0542fb Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 9 Jan 2021 14:19:40 -0700 Subject: [PATCH] Add lazy utility --- src/spectator/block.cr | 13 +++---------- src/spectator/lazy.cr | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 src/spectator/lazy.cr diff --git a/src/spectator/block.cr b/src/spectator/block.cr index 15553dd..312681a 100644 --- a/src/spectator/block.cr +++ b/src/spectator/block.cr @@ -1,6 +1,6 @@ require "./abstract_expression" require "./label" -require "./wrapper" +require "./lazy" module Spectator # Represents a block from a test. @@ -10,8 +10,7 @@ module Spectator # or nil if one isn't available. class Block(T) < AbstractExpression # Cached value returned from the block. - # Is nil if the block hasn't been called. - @wrapper : Wrapper(T)? + @value = Lazy(T).new # Creates the block expression from a proc. # 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. # Afterwards, the value is cached and returned by successive calls to this method. def value - if (wrapper = @wrapper) - wrapper.value - else - call.tap do |value| - @wrapper = Wrapper.new(value) - end - end + @value.get { call } end # Evaluates the block and returns the value from it. diff --git a/src/spectator/lazy.cr b/src/spectator/lazy.cr new file mode 100644 index 0000000..afeee5f --- /dev/null +++ b/src/spectator/lazy.cr @@ -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