Create value wrapper

This commit is contained in:
Michael Miller 2021-01-09 16:51:37 -07:00
parent aa4c257ade
commit 3e4b77da77
No known key found for this signature in database
GPG key ID: F9A0C5C65B162436
2 changed files with 60 additions and 0 deletions

View file

@ -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

41
src/spectator/wrapper.cr Normal file
View file

@ -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