Skip to content

Commit 121e18d

Browse files
authored
Merge pull request #56 from michaeldiscala/optimize-initializer
Optimize initializer
2 parents 8b78d97 + 56f393b commit 121e18d

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

lib/values.rb

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,28 @@ def self.new(*fields, &block)
2323
Class.new do
2424
attr_reader(:hash, *fields)
2525

26-
define_method(:initialize) do |*values|
27-
raise ArgumentError.new("wrong number of arguments, #{values.size} for #{fields.size}") if fields.size != values.size
26+
# Unroll the fields into a series of assignment Ruby statements that can
27+
# be used inside of the initializer for the new class. This was introduced
28+
# in PR#56 as a performance optimization -- it ensures that this iteration
29+
# happens once per class, instead of happening once per instance of the
30+
# class.
31+
instance_var_assignments = Array.new(fields.length) do |idx|
32+
"@#{fields[idx]} = values[#{idx}]"
33+
end.join("\n")
34+
35+
class_eval <<-RUBY
36+
def initialize(*values)
37+
if #{fields.size} != values.size
38+
raise ArgumentError.new("wrong number of arguments, \#{values.size} for #{fields.size}")
39+
end
2840
29-
fields.zip(values) do |field, value|
30-
instance_variable_set(:"@#{field}", value)
31-
end
41+
#{instance_var_assignments}
3242
33-
@hash = self.class.hash ^ values.hash
43+
@hash = self.class.hash ^ values.hash
3444
35-
freeze
36-
end
45+
freeze
46+
end
47+
RUBY
3748

3849
const_set :VALUE_ATTRS, fields
3950

0 commit comments

Comments
 (0)