Value Struct
A value struct is a subclass of normal Ruby struct that behaves almost the same. However, it has a major difference:
Value structs are immutable, i.e. they don't have setters (although, not recursively*)
Additionally, this gem provides the following optional mixins to make life easier when using immutable structs:
- :dup_with_changes #dup takes a optional hash for setting new values in the duplicate
:to_h #to_h for converting into a valuestruct into a hash (if Ruby version below < 2.0)
:strict_arguments Value structs need to be initialized with the exact amount of arguments
:freeze Automatically freezes new instances
:no_clone #clone does not clone, but return the same object
By default, only :dup_with_changes and :to_h get included.
Why?
Sometimes you want to eliminate state. See [this blog article] for more information.
Performance
Without mixins, ValueStructs are as fast as normal structs. Some (optional) mixins add noticable overhead, e.g. strict_arguments
Example
require 'value_struct'
Point = ValueStruct.new(:x, :y) do # methods defined in the block will be available in your new value struct class
# ...
end
Please refer to the [documentation of Ruby's struct] for more details on usage.
How to use structs with mixins
Point = ValueStruct.new_with_mixins :x, :y, [
ValueStruct::ToH,
ValueStruct::Freeze,
ValueStruct::DupWithChanges,
ValueStruct::StrictArguments,
]
p = Point.new(1,2)
p.to_h #=> { :x => 1, :y => 2 }
p.frozen? #=> true
p.dup(x: 0) #=> #<ValueStruct Point x=0, y=2>
Point.new(1) # ArgumentError
*
Because of the nature of Ruby, most things are not really immutable. So if you have an attribute :by
and initialize it with an array, you cannot change the value struct anymore, but still the array:
Ru = ValueStruct.new(:by)
ruby = Ru.by([1,2,3])
ruby.by # => [1,2,3]
ruby.by = [1,2,3,4] # not possible
ruby.by << 4 # possible
Install
$ gem install value_struct
Influenced by / Thanks to
- Tom Crayford: Values
- Theo Hultberg: ImmutableStruct
- Ruby Rogues