Class: Struct
Overview
Class Struct provides a convenient way to create a simple class that can store and fetch values.
This example creates a subclass of Struct
, Struct::Customer
; the first argument, a string, is the name of the subclass; the other arguments, symbols, determine the members of the new subclass.
Customer = Struct.new('Customer', :name, :address, :zip)
Customer.name # => "Struct::Customer"
Customer.class # => Class
Customer.superclass # => Struct
Corresponding to each member are two methods, a writer and a reader, that store and fetch values:
methods = Customer.instance_methods false
methods # => [:zip, :address=, :zip=, :address, :name, :name=]
An instance of the subclass may be created, and its members assigned values, via method ::new
:
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe # => #<struct Struct::Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=12345>
The member values may be managed thus:
joe.name # => "Joe Smith"
joe.name = 'Joseph Smith'
joe.name # => "Joseph Smith"
And thus; note that member name may be expressed as either a string or a symbol:
joe[:name] # => "Joseph Smith"
joe[:name] = 'Joseph Smith, Jr.'
joe['name'] # => "Joseph Smith, Jr."
See Struct::new.
What’s Here
First, what’s elsewhere. Class Struct:
-
Inherits from class Object.
-
Includes module Enumerable, which provides dozens of additional methods.
See also Data, which is a somewhat similar, but stricter concept for defining immutable value objects.
Here, class Struct provides methods that are useful for:
Methods for Creating a Struct Subclass
-
::new: Returns a new subclass of Struct.
Methods for Querying
-
#hash: Returns the integer hash code.
-
#size (aliased as #length): Returns the number of members.
Methods for Comparing
-
#==: Returns whether a given object is equal to
self
, using==
to compare member values. -
#eql?: Returns whether a given object is equal to
self
, usingeql?
to compare member values.
Methods for Fetching
-
#[]: Returns the value associated with a given member name.
-
#to_a (aliased as #values, #deconstruct): Returns the member values in
self
as an array. -
#deconstruct_keys: Returns a hash of the name/value pairs for given member names.
-
#dig: Returns the object in nested objects that is specified by a given member name and additional arguments.
-
#members: Returns an array of the member names.
-
#select (aliased as #filter): Returns an array of member values from
self
, as selected by the given block. -
#values_at: Returns an array containing values for given member names.
Methods for Assigning
-
#[]=: Assigns a given value to a given member name.
Methods for Iterating
-
#each: Calls a given block with each member name.
-
#each_pair: Calls a given block with each member name/value pair.
Methods for Converting
-
#inspect (aliased as #to_s): Returns a string representation of
self
. -
#to_h: Returns a hash of the member name/value pairs in
self
.
Class Method Summary collapse
-
.StructClass::keyword_init? ⇒ true
Returns
true
if the class was initialized withkeyword_init: true
. -
.StructClass::members ⇒ Object
Returns the member names of the Struct descendant as an array:.
-
.new(*args) ⇒ Object
Struct.new
returns a new subclass ofStruct
.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Returns
true
if and only if the following are true; otherwise returnsfalse
:. -
#[](idx) ⇒ Object
Returns a value from
self
. -
#[]=(idx, val) ⇒ Object
Assigns a value to a member.
-
#to_a ⇒ Array
Returns the values in
self
as an array:. -
#deconstruct_keys(array_of_names) ⇒ Hash
Returns a hash of the name/value pairs for the given member names.
-
#dig(*args) ⇒ Object
Finds and returns an object among nested objects.
-
#each ⇒ Object
Calls the given block with the value of each member; returns
self
:. -
#each_pair ⇒ Object
Calls the given block with each member name/value pair; returns
self
:. -
#eql?(other) ⇒ Boolean
Returns
true
if and only if the following are true; otherwise returnsfalse
:. -
#filter(*args) ⇒ Object
With a block given, returns an array of values from
self
for which the block returns a truthy value:. -
#hash ⇒ Integer
Returns the integer hash value for
self
. - #initialize(*args) ⇒ Object constructor
-
#initialize_copy(s) ⇒ Object
:nodoc:.
-
#inspect ⇒ String
(also: #to_s)
Returns a string representation of
self
:. -
#size ⇒ Integer
Returns the number of members.
-
#members ⇒ Object
Returns the member names from
self
as an array:. -
#select(*args) ⇒ Object
With a block given, returns an array of values from
self
for which the block returns a truthy value:. -
#size ⇒ Integer
Returns the number of members.
-
#to_a ⇒ Array
Returns the values in
self
as an array:. -
#to_h ⇒ Object
Returns a hash containing the name and value for each member:.
-
#to_a ⇒ Array
Returns the values in
self
as an array:. -
#values_at(*args) ⇒ Object
Returns an array of values from
self
.
Methods included from Enumerable
#all?, #any?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #compact, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter_map, #find, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #include?, #inject, #lazy, #map, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #uniq, #zip
Constructor Details
#initialize(*args) ⇒ Object
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 |
# File 'struct.c', line 740
static VALUE
rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
{
VALUE klass = rb_obj_class(self);
rb_struct_modify(self);
long n = num_members(klass);
if (argc == 0) {
rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n);
return Qnil;
}
bool keyword_init = false;
switch (rb_struct_s_keyword_init(klass)) {
default:
if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
rb_error_arity(argc, 0, 0);
}
keyword_init = true;
break;
case Qfalse:
break;
case Qnil:
if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
break;
}
keyword_init = rb_keyword_given_p();
break;
}
if (keyword_init) {
struct struct_hash_set_arg arg;
rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n);
arg.self = self;
arg.unknown_keywords = Qnil;
rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
if (arg.unknown_keywords != Qnil) {
rb_raise(rb_eArgError, "unknown keywords: %s",
RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
}
}
else {
if (n < argc) {
rb_raise(rb_eArgError, "struct size differs");
}
for (long i=0; i<argc; i++) {
RSTRUCT_SET(self, i, argv[i]);
}
if (n > argc) {
rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc);
}
}
return Qnil;
}
|
Class Method Details
.StructClass::keyword_init? ⇒ true
343 344 345 346 |
# File 'struct.c', line 343 static VALUE rb_struct_s_keyword_init_p(VALUE obj) { } |
.StructClass::members ⇒ Object
205 206 207 208 209 210 211 |
# File 'struct.c', line 205
static VALUE
rb_struct_s_members_m(VALUE klass)
{
VALUE members = rb_struct_s_members(klass);
return rb_ary_dup(members);
}
|
.new(*member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct_subclass .new(class_name, *member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct_subclass .new(*member_names) ⇒ Struct_subclass_instance .new(**member_names) ⇒ Struct_subclass_instance
Struct.new
returns a new subclass of Struct
. The new subclass:
-
May be anonymous, or may have the name given by
class_name
. -
May have members as given by
member_names
. -
May have initialization via ordinary arguments, or via keyword arguments
The new subclass has its own method ::new
; thus:
Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo
f = Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1>
Class Name
With string argument class_name
, returns a new subclass of Struct
named Struct::class_name
:
Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo
Foo.name # => "Struct::Foo"
Foo.superclass # => Struct
Without string argument class_name
, returns a new anonymous subclass of Struct
:
Struct.new(:foo, :bar).name # => nil
Block
With a block given, the created subclass is yielded to the block:
Customer = Struct.new('Customer', :name, :address) do |new_class|
p "The new subclass is #{new_class}"
def greeting
"Hello #{name} at #{address}"
end
end # => Struct::Customer
dave = Customer.new('Dave', '123 Main')
dave # => #<struct Struct::Customer name="Dave", address="123 Main">
dave.greeting # => "Hello Dave at 123 Main"
Output, from Struct.new
:
"The new subclass is Struct::Customer"
Member Names
Symbol arguments member_names
determines the members of the new subclass:
Struct.new(:foo, :bar).members # => [:foo, :bar]
Struct.new('Foo', :foo, :bar).members # => [:foo, :bar]
The new subclass has instance methods corresponding to member_names
:
Foo = Struct.new('Foo', :foo, :bar)
Foo.instance_methods(false) # => [:foo, :bar, :foo=, :bar=]
f = Foo.new # => #<struct Struct::Foo foo=nil, bar=nil>
f.foo # => nil
f.foo = 0 # => 0
f. # => nil
f. = 1 # => 1
f # => #<struct Struct::Foo foo=0, bar=1>
Singleton Methods
A subclass returned by Struct.new has these singleton methods:
-
Method
::new
creates an instance of the subclass:Foo.new # => #<struct Struct::Foo foo=nil, bar=nil> Foo.new(0) # => #<struct Struct::Foo foo=0, bar=nil> Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1> Foo.new(0, 1, 2) # Raises ArgumentError: struct size differs # Initialization with keyword arguments: Foo.new(foo: 0) # => #<struct Struct::Foo foo=0, bar=nil> Foo.new(foo: 0, bar: 1) # => #<struct Struct::Foo foo=0, bar=1> Foo.new(foo: 0, bar: 1, baz: 2) # Raises ArgumentError: unknown keywords: baz
-
Method
:inspect
returns a string representation of the subclass:Foo.inspect # => "Struct::Foo"
-
Method
::members
returns an array of the member names:Foo.members # => [:foo, :bar]
Keyword Argument
By default, the arguments for initializing an instance of the new subclass can be both positional and keyword arguments.
Optional keyword argument keyword_init:
allows to force only one type of arguments to be accepted:
KeywordsOnly = Struct.new(:foo, :bar, keyword_init: true)
KeywordsOnly.new(bar: 1, foo: 0)
# => #<struct KeywordsOnly foo=0, bar=1>
KeywordsOnly.new(0, 1)
# Raises ArgumentError: wrong number of arguments
PositionalOnly = Struct.new(:foo, :bar, keyword_init: false)
PositionalOnly.new(0, 1)
# => #<struct PositionalOnly foo=0, bar=1>
PositionalOnly.new(bar: 1, foo: 0)
# => #<struct PositionalOnly foo={:foo=>1, :bar=>2}, bar=nil>
# Note that no error is raised, but arguments treated as one hash value
# Same as not providing keyword_init:
Any = Struct.new(:foo, :bar, keyword_init: nil)
Any.new(foo: 1, bar: 2)
# => #<struct Any foo=1, bar=2>
Any.new(1, 2)
# => #<struct Any foo=1, bar=2>
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'struct.c', line 641
static VALUE
rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
{
VALUE name = Qnil, rest, keyword_init = Qnil;
long i;
VALUE st;
VALUE opt;
argc = rb_scan_args(argc, argv, "0*:", NULL, &opt);
if (argc >= 1 && !SYMBOL_P(argv[0])) {
name = argv[0];
--argc;
++argv;
}
if (!NIL_P(opt)) {
static ID keyword_ids[1];
if (!keyword_ids[0]) {
keyword_ids[0] = rb_intern("keyword_init");
}
rb_get_kwargs(opt, keyword_ids, 0, 1, &keyword_init);
if (UNDEF_P(keyword_init)) {
keyword_init = Qnil;
}
else if (RTEST(keyword_init)) {
keyword_init = Qtrue;
}
}
rest = rb_ident_hash_new();
RBASIC_CLEAR_CLASS(rest);
for (i=0; i<argc; i++) {
VALUE mem = rb_to_symbol(argv[i]);
if (rb_is_attrset_sym(mem)) {
rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
}
if (RTEST(rb_hash_has_key(rest, mem))) {
rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
}
rb_hash_aset(rest, mem, Qtrue);
}
rest = rb_hash_keys(rest);
RBASIC_CLEAR_CLASS(rest);
OBJ_FREEZE(rest);
if (NIL_P(name)) {
st = anonymous_struct(klass);
}
else {
st = new_struct(name, klass);
}
setup_struct(st, rest);
rb_ivar_set(st, id_keyword_init, keyword_init);
if (rb_block_given_p()) {
rb_mod_module_eval(0, 0, st);
}
return st;
}
|
Instance Method Details
#==(other) ⇒ Boolean
Returns true
if and only if the following are true; otherwise returns false
:
-
other.class == self.class
. -
For each member name
name
,other.name == self.name
.
Examples:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe_jr == joe # => true
joe_jr[:name] = 'Joe Smith, Jr.'
# => "Joe Smith, Jr."
joe_jr == joe # => false
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 |
# File 'struct.c', line 1398
static VALUE
rb_struct_equal(VALUE s, VALUE s2)
{
if (s == s2) return Qtrue;
if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
rb_bug("inconsistent struct"); /* should never happen */
}
return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
}
|
#[](name) ⇒ Object #[](n) ⇒ Object
Returns a value from self
.
With symbol or string argument name
given, returns the value for the named member:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe[:zip] # => 12345
Raises NameError if name
is not the name of a member.
With integer argument n
given, returns self.values[n]
if n
is in range; see Array@Array+Indexes:
joe[2] # => 12345
joe[-2] # => "123 Maple, Anytown NC"
Raises IndexError if n
is out of range.
1216 1217 1218 1219 1220 1221 1222 |
# File 'struct.c', line 1216
VALUE
rb_struct_aref(VALUE s, VALUE idx)
{
int i = rb_struct_pos(s, &idx);
if (i < 0) invalid_struct_pos(s, idx);
return RSTRUCT_GET(s, i);
}
|
#[]=(name) ⇒ Object #[]=(n) ⇒ Object
Assigns a value to a member.
With symbol or string argument name
given, assigns the given value
to the named member; returns value
:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe[:zip] = 54321 # => 54321
joe # => #<struct Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=54321>
Raises NameError if name
is not the name of a member.
With integer argument n
given, assigns the given value
to the n
-th member if n
is in range; see Array@Array+Indexes:
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe[2] = 54321 # => 54321
joe[-3] = 'Joseph Smith' # => "Joseph Smith"
joe # => #<struct Customer name="Joseph Smith", address="123 Maple, Anytown NC", zip=54321>
Raises IndexError if n
is out of range.
1254 1255 1256 1257 1258 1259 1260 1261 1262 |
# File 'struct.c', line 1254
VALUE
rb_struct_aset(VALUE s, VALUE idx, VALUE val)
{
int i = rb_struct_pos(s, &idx);
if (i < 0) invalid_struct_pos(s, idx);
rb_struct_modify(s);
RSTRUCT_SET(s, i, val);
return val;
}
|
#to_a ⇒ Array
1026 1027 1028 1029 1030 |
# File 'struct.c', line 1026
static VALUE
rb_struct_to_a(VALUE s)
{
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s));
}
|
#deconstruct_keys(array_of_names) ⇒ Hash
Returns a hash of the name/value pairs for the given member names.
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
h = joe.deconstruct_keys([:zip, :address])
h # => {:zip=>12345, :address=>"123 Maple, Anytown NC"}
Returns all names and values if array_of_names
is nil
:
h = joe.deconstruct_keys(nil)
h # => {:name=>"Joseph Smith, Jr.", :address=>"123 Maple, Anytown NC", :zip=>12345}
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 |
# File 'struct.c', line 1090
static VALUE
rb_struct_deconstruct_keys(VALUE s, VALUE keys)
{
VALUE h;
long i;
if (NIL_P(keys)) {
return rb_struct_to_h(s);
}
if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
rb_raise(rb_eTypeError,
"wrong argument type %"PRIsVALUE" (expected Array or nil)",
rb_obj_class(keys));
}
if (RSTRUCT_LEN(s) < RARRAY_LEN(keys)) {
return rb_hash_new_with_size(0);
}
h = rb_hash_new_with_size(RARRAY_LEN(keys));
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE key = RARRAY_AREF(keys, i);
int i = rb_struct_pos(s, &key);
if (i < 0) {
return h;
}
rb_hash_aset(h, key, RSTRUCT_GET(s, i));
}
return h;
}
|
#dig(name, *identifiers) ⇒ Object #dig(n, *identifiers) ⇒ Object
Finds and returns an object among nested objects.
The nested objects may be instances of various classes.
See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
Given symbol or string argument +name+,
returns the object that is specified by +name+ and +identifiers+:
Foo = Struct.new(:a)
f = Foo.new(Foo.new({b: [1, 2, 3]}))
f.dig(:a) # => #<struct Foo a={:b=>[1, 2, 3]}>
f.dig(:a, :a) # => {:b=>[1, 2, 3]}
f.dig(:a, :a, :b) # => [1, 2, 3]
f.dig(:a, :a, :b, 0) # => 1
f.dig(:b, 0) # => nil
Given integer argument +n+,
returns the object that is specified by +n+ and +identifiers+:
f.dig(0) # => #<struct Foo a={:b=>[1, 2, 3]}>
f.dig(0, 0) # => {:b=>[1, 2, 3]}
f.dig(0, 0, :b) # => [1, 2, 3]
f.dig(0, 0, :b, 0) # => 1
f.dig(:b, 0) # => nil
1542 1543 1544 1545 1546 1547 1548 1549 1550 |
# File 'struct.c', line 1542
static VALUE
rb_struct_dig(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
self = rb_struct_lookup(self, *argv);
if (!--argc) return self;
++argv;
return rb_obj_dig(argc, argv, self, Qnil);
}
|
#each {|value| ... } ⇒ self #each ⇒ Object
Calls the given block with the value of each member; returns self
:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each {|value| p value }
Output:
"Joe Smith"
"123 Maple, Anytown NC"
12345
Returns an Enumerator if no block is given.
Related: #each_pair.
890 891 892 893 894 895 896 897 898 899 900 |
# File 'struct.c', line 890
static VALUE
rb_struct_each(VALUE s)
{
long i;
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
for (i=0; i<RSTRUCT_LEN(s); i++) {
rb_yield(RSTRUCT_GET(s, i));
}
return s;
}
|
#each_pair {|(name, value)| ... } ⇒ self #each_pair ⇒ Object
Calls the given block with each member name/value pair; returns self
:
Customer = Struct.new(:name, :address, :zip) # => Customer
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each_pair {|(name, value)| p "#{name} => #{value}" }
Output:
"name => Joe Smith"
"address => 123 Maple, Anytown NC"
"zip => 12345"
Returns an Enumerator if no block is given.
Related: #each.
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'struct.c', line 925
static VALUE
rb_struct_each_pair(VALUE s)
{
VALUE members;
long i;
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
members = rb_struct_members(s);
if (rb_block_pair_yield_optimizable()) {
for (i=0; i<RSTRUCT_LEN(s); i++) {
VALUE key = rb_ary_entry(members, i);
VALUE value = RSTRUCT_GET(s, i);
rb_yield_values(2, key, value);
}
}
else {
for (i=0; i<RSTRUCT_LEN(s); i++) {
VALUE key = rb_ary_entry(members, i);
VALUE value = RSTRUCT_GET(s, i);
rb_yield(rb_assoc_new(key, value));
}
}
return s;
}
|
#eql?(other) ⇒ Boolean
Returns true
if and only if the following are true; otherwise returns false
:
- <tt>other.class == self.class</tt>.
- For each member name +name+, <tt>other.name.eql?(self.name)</tt>.
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe_jr.eql?(joe) # => true
joe_jr[:name] = 'Joe Smith, Jr.'
joe_jr.eql?(joe) # => false
Related: Object#==.
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 |
# File 'struct.c', line 1479
static VALUE
rb_struct_eql(VALUE s, VALUE s2)
{
if (s == s2) return Qtrue;
if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
rb_bug("inconsistent struct"); /* should never happen */
}
return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
}
|
#select {|value| ... } ⇒ Array #select ⇒ Object
With a block given, returns an array of values from self
for which the block returns a truthy value:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
a = joe.select {|value| value.is_a?(String) }
a # => ["Joe Smith", "123 Maple, Anytown NC"]
a = joe.select {|value| value.is_a?(Integer) }
a # => [12345]
With no block given, returns an Enumerator.
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 |
# File 'struct.c', line 1346
static VALUE
rb_struct_select(int argc, VALUE *argv, VALUE s)
{
VALUE result;
long i;
rb_check_arity(argc, 0, 0);
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
result = rb_ary_new();
for (i = 0; i < RSTRUCT_LEN(s); i++) {
if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
rb_ary_push(result, RSTRUCT_GET(s, i));
}
}
return result;
}
|
#hash ⇒ Integer
Returns the integer hash value for self
.
Two structs of the same class and with the same content will have the same hash code (and will compare using Struct#eql?):
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe_jr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.hash == joe_jr.hash # => true
joe_jr[:name] = 'Joe Smith, Jr.'
joe.hash == joe_jr.hash # => false
Related: Object#hash.
1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 |
# File 'struct.c', line 1430
static VALUE
rb_struct_hash(VALUE s)
{
long i, len;
st_index_t h;
VALUE n;
h = rb_hash_start(rb_hash(rb_obj_class(s)));
len = RSTRUCT_LEN(s);
for (i = 0; i < len; i++) {
n = rb_hash(RSTRUCT_GET(s, i));
h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
}
|
#initialize_copy(s) ⇒ Object
:nodoc:
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 |
# File 'struct.c', line 1121
VALUE
rb_struct_init_copy(VALUE copy, VALUE s)
{
long i, len;
if (!OBJ_INIT_COPY(copy, s)) return copy;
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
rb_raise(rb_eTypeError, "struct size mismatch");
}
for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
}
return copy;
}
|
#inspect ⇒ String Also known as: to_s
1007 1008 1009 1010 1011 |
# File 'struct.c', line 1007
static VALUE
rb_struct_inspect(VALUE s)
{
return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<struct "));
}
|
#size ⇒ Integer
1504 1505 1506 1507 1508 |
# File 'struct.c', line 1504
VALUE
rb_struct_size(VALUE s)
{
return LONG2FIX(RSTRUCT_LEN(s));
}
|
#members ⇒ Object
225 226 227 228 229 |
# File 'struct.c', line 225
static VALUE
rb_struct_members_m(VALUE obj)
{
return rb_struct_s_members_m(rb_obj_class(obj));
}
|
#select {|value| ... } ⇒ Array #select ⇒ Object
With a block given, returns an array of values from self
for which the block returns a truthy value:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
a = joe.select {|value| value.is_a?(String) }
a # => ["Joe Smith", "123 Maple, Anytown NC"]
a = joe.select {|value| value.is_a?(Integer) }
a # => [12345]
With no block given, returns an Enumerator.
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 |
# File 'struct.c', line 1346
static VALUE
rb_struct_select(int argc, VALUE *argv, VALUE s)
{
VALUE result;
long i;
rb_check_arity(argc, 0, 0);
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
result = rb_ary_new();
for (i = 0; i < RSTRUCT_LEN(s); i++) {
if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
rb_ary_push(result, RSTRUCT_GET(s, i));
}
}
return result;
}
|
#size ⇒ Integer
1504 1505 1506 1507 1508 |
# File 'struct.c', line 1504
VALUE
rb_struct_size(VALUE s)
{
return LONG2FIX(RSTRUCT_LEN(s));
}
|
#to_a ⇒ Array
1026 1027 1028 1029 1030 |
# File 'struct.c', line 1026
static VALUE
rb_struct_to_a(VALUE s)
{
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s));
}
|
#to_h ⇒ Hash #to_h {|name, value| ... } ⇒ Hash
Returns a hash containing the name and value for each member:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
h = joe.to_h
h # => {:name=>"Joe Smith", :address=>"123 Maple, Anytown NC", :zip=>12345}
If a block is given, it is called with each name/value pair; the block should return a 2-element array whose elements will become a key/value pair in the returned hash:
h = joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}
h # => {:NAME=>"JOE SMITH", :ADDRESS=>"123 MAPLE, ANYTOWN NC", :ZIP=>"12345"}
Raises ArgumentError if the block returns an inappropriate value.
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 |
# File 'struct.c', line 1055
static VALUE
rb_struct_to_h(VALUE s)
{
VALUE h = rb_hash_new_with_size(RSTRUCT_LEN(s));
VALUE members = rb_struct_members(s);
long i;
int block_given = rb_block_given_p();
for (i=0; i<RSTRUCT_LEN(s); i++) {
VALUE k = rb_ary_entry(members, i), v = RSTRUCT_GET(s, i);
if (block_given)
rb_hash_set_pair(h, rb_yield_values(2, k, v));
else
rb_hash_aset(h, k, v);
}
return h;
}
|
#to_a ⇒ Array
1026 1027 1028 1029 1030 |
# File 'struct.c', line 1026
static VALUE
rb_struct_to_a(VALUE s)
{
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s));
}
|
#values_at(*integers) ⇒ Array #values_at(integer_range) ⇒ Array
Returns an array of values from self
.
With integer arguments integers
given, returns an array containing each value given by one of integers
:
Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.values_at(0, 2) # => ["Joe Smith", 12345]
joe.values_at(2, 0) # => [12345, "Joe Smith"]
joe.values_at(2, 1, 0) # => [12345, "123 Maple, Anytown NC", "Joe Smith"]
joe.values_at(0, -3) # => ["Joe Smith", "Joe Smith"]
Raises IndexError if any of integers
is out of range; see Array@Array+Indexes.
With integer range argument integer_range
given, returns an array containing each value given by the elements of the range; fills with nil
values for range elements larger than the structure:
joe.values_at(0..2)
# => ["Joe Smith", "123 Maple, Anytown NC", 12345]
joe.values_at(-3..-1)
# => ["Joe Smith", "123 Maple, Anytown NC", 12345]
joe.values_at(1..4) # => ["123 Maple, Anytown NC", 12345, nil, nil]
Raises RangeError if any element of the range is negative and out of range; see Array@Array+Indexes.
1322 1323 1324 1325 1326 |
# File 'struct.c', line 1322
static VALUE
rb_struct_values_at(int argc, VALUE *argv, VALUE s)
{
return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
}
|