From 3e4b77da776ec2438dcb911827d4e2f73553533f Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 9 Jan 2021 16:51:37 -0700 Subject: [PATCH] Create value wrapper --- src/spectator/lazy_wrapper.cr | 19 ++++++++++++++++ src/spectator/wrapper.cr | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/spectator/lazy_wrapper.cr create mode 100644 src/spectator/wrapper.cr diff --git a/src/spectator/lazy_wrapper.cr b/src/spectator/lazy_wrapper.cr new file mode 100644 index 0000000..438e58b --- /dev/null +++ b/src/spectator/lazy_wrapper.cr @@ -0,0 +1,19 @@ +require "./lazy" +require "./wrapper" + +module Spectator + # Lazily stores a value of any type. + # Combines `Lazy` and `Wrapper`. + struct LazyWrapper + @lazy = Lazy(Wrapper).new + + # 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(type : T.class, &block : -> T) : T forall T + wrapper = @lazy.get { Wrapper.new(yield) } + wrapper.get(type) + end + end +end diff --git a/src/spectator/wrapper.cr b/src/spectator/wrapper.cr new file mode 100644 index 0000000..efee1b6 --- /dev/null +++ b/src/spectator/wrapper.cr @@ -0,0 +1,41 @@ +module Spectator + # Typeless wrapper for a value. + # Stores any value or reference type. + # However, the type must be known when retrieving the value. + struct Wrapper + @value : TypelessValue + + # Creates a wrapper for the specified value. + def initialize(value) + @value = Value.new(value) + end + + # Retrieves the previously wrapped value. + # The *type* of the wrapped value must match otherwise an error will be raised. + def get(type : T.class) : T forall T + value = @value.as(Value(T)) + value.get + end + + # Base type that generic types inherit from. + # This provides a common base type, + # since Crystal doesn't support storing an `Object` (yet). + # Instances of this type must be downcast to `Value` to be useful. + private abstract class TypelessValue + end + + # Generic value wrapper. + # Simply holds a value and inherits from `TypelessValue`, + # so that all types of this class can be stored as one. + private class Value(T) < TypelessValue + # Creates the wrapper with the specified value. + def initialize(@value : T) + end + + # Retrieves the wrapped value. + def get : T + @value + end + end + end +end