A Ruby Struct allows an instance to be generated with a set of accessors:
# Create a structure named by its constant
Customer = Struct.new(:name, :address) #
Regarding comments about the speed of using Hashes, Struct or OpenStruct: Hash will always win for general use. It's the basis of OpenStruct without the additional icing so it's not as flexible, but it's lean and mean.
Using Ruby 2.4.1:
require 'fruity'
require 'ostruct'
def _hash
h = {}
h['a'] = 1
h['a']
end
def _struct
s = Struct.new(:a)
foo = s.new(1)
foo.a
end
def _ostruct
person = OpenStruct.new
person.a = 1
person.a
end
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Running each test 4096 times. Test will take about 2 seconds.
# >> a_hash is faster than an_ostruct by 13x ± 1.0
# >> an_ostruct is similar to a_struct
Using more concise definitions of the hash and OpenStruct:
require 'fruity'
require 'ostruct'
def _hash
h = {'a' => 1}
h['a']
end
def _struct
s = Struct.new(:a)
foo = s.new(1)
foo.a
end
def _ostruct
person = OpenStruct.new('a' => 1)
person.a
end
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Running each test 4096 times. Test will take about 2 seconds.
# >> a_hash is faster than an_ostruct by 17x ± 10.0
# >> an_ostruct is similar to a_struct
If the structure, Hash or Struct or OpenStruct is defined once then used many times, then the access speed becomes more important, and a Struct begins to shine:
require 'fruity'
require 'ostruct'
HSH = {'a' => 1}
def _hash
HSH['a']
end
STRCT = Struct.new(:a).new(1)
def _struct
STRCT.a
end
OSTRCT = OpenStruct.new('a' => 1)
def _ostruct
OSTRCT.a
end
puts "Ruby version: #{RUBY_VERSION}"
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Ruby version: 2.4.1
# >> Running each test 65536 times. Test will take about 2 seconds.
# >> a_struct is faster than a_hash by 4x ± 1.0
# >> a_hash is similar to an_ostruct
Notice though, that the Struct is only 4x faster than the Hash for accessing, whereas the Hash is 17x faster for initialization, assignment and accessing. You'll have to figure out which is the best to use based on the needs of a particular application. I tend to use Hashes for general use as a result.
Also, the speed of using OpenStruct has improved greatly over the years; It used to be slower than Struct based on benchmarks I've seen in the past and comparing to 1.9.3-p551:
require 'fruity'
require 'ostruct'
def _hash
h = {}
h['a'] = 1
h['a']
end
def _struct
s = Struct.new(:a)
foo = s.new(1)
foo.a
end
def _ostruct
person = OpenStruct.new
person.a = 1
person.a
end
puts "Ruby version: #{RUBY_VERSION}"
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Ruby version: 1.9.3
# >> Running each test 4096 times. Test will take about 2 seconds.
# >> a_hash is faster than a_struct by 7x ± 1.0
# >> a_struct is faster than an_ostruct by 2x ± 0.1
and:
require 'fruity'
require 'ostruct'
def _hash
h = {'a' => 1}
h['a']
end
def _struct
s = Struct.new(:a)
foo = s.new(1)
foo.a
end
def _ostruct
person = OpenStruct.new('a' => 1)
person.a
end
puts "Ruby version: #{RUBY_VERSION}"
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Ruby version: 1.9.3
# >> Running each test 4096 times. Test will take about 2 seconds.
# >> a_hash is faster than a_struct by 7x ± 1.0
# >> a_struct is faster than an_ostruct by 2x ± 1.0
and:
require 'fruity'
require 'ostruct'
HSH = {'a' => 1}
def _hash
HSH['a']
end
STRCT = Struct.new(:a).new(1)
def _struct
STRCT.a
end
OSTRCT = OpenStruct.new('a' => 1)
def _ostruct
OSTRCT.a
end
puts "Ruby version: #{RUBY_VERSION}"
compare do
a_hash { _hash }
a_struct { _struct }
an_ostruct { _ostruct }
end
# >> Ruby version: 1.9.3
# >> Running each test 32768 times. Test will take about 1 second.
# >> a_struct is faster than an_ostruct by 3x ± 1.0
# >> an_ostruct is similar to a_hash