Class: Struct
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
::Enumerable
|
|
| Inherits: | Object |
| Defined in: | struct.c, struct.c |
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 .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
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, using #eql? to compare member values.
Methods for Fetching
-
#[]: Returns the value associated with a given member name.
-
#to_a, #values, #deconstruct: Returns the member values in
selfas 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, #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
Class Attribute Summary
-
StructClass.keyword_init? ⇒ Boolean
readonly
Returns
trueif the class was initialized withkeyword_init: true.
Class Method Summary
-
StructClass.members ⇒ array_of_symbols
Returns the member names of the
Structdescendant as an array: -
.new(*member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct
constructor
newreturns a new subclass ofStruct.
Instance Method Summary
-
#==(other) ⇒ Boolean
Returns
trueif and only if the following are true; otherwise returnsfalse: -
#[](name) ⇒ Object
Returns a value from
self. -
#[]=(name, value) ⇒ value
Assigns a value to a member.
-
#deconstruct ⇒ Array
Alias for #to_a.
-
#deconstruct_keys(array_of_names) ⇒ Hash
Returns a hash of the name/value pairs for the given member names.
-
#dig(name, *identifiers) ⇒ Object
Finds and returns an object among nested objects.
-
#each {|value| ... } ⇒ self
Calls the given block with the value of each member; returns
self: -
#each_pair {|(name, value)| ... } ⇒ self
Calls the given block with each member name/value pair; returns
self: -
#eql?(other) ⇒ Boolean
Returns
trueif and only if the following are true; otherwise returnsfalse: -
#select {|value| ... } ⇒ Array
(also: #select)
With a block given, returns an array of values from
selffor which the block returns a truthy value: -
#hash ⇒ Integer
Returns the integer hash value for
self. - #initialize(*args) constructor
-
#inspect ⇒ String
Alias for #to_s.
-
#length ⇒ Integer
(also: #size)
Returns the number of members.
-
#members ⇒ array_of_symbols
Returns the member names from
selfas an array: -
#select {|value| ... } ⇒ Array
Alias for #filter.
-
#size ⇒ Integer
Alias for #length.
-
#to_a ⇒ Array
(also: #values, #deconstruct)
Returns the values in
selfas an array: -
#to_h ⇒ Hash
Returns a hash containing the name and value for each member:
-
#to_s ⇒ String
(also: #inspect)
Returns a string representation of
self: -
#values ⇒ Array
Alias for #to_a.
-
#values_at(*integers) ⇒ Array
Returns an array of values from
self. - #initialize_copy(s) Internal use only
::Enumerable - Included
| #all? | Returns whether every element meets a given criterion. |
| #any? | Returns whether any element meets a given criterion. |
| #chain | Returns an enumerator object generated from this enumerator and given enumerables. |
| #chunk | Each element in the returned enumerator is a 2-element array consisting of: |
| #chunk_while | Creates an enumerator for each chunked elements. |
| #collect | Alias for Enumerable#map. |
| #collect_concat | Alias for Enumerable#flat_map. |
| #compact | Returns an array of all non- |
| #count | Returns the count of elements, based on an argument or block criterion, if given. |
| #cycle | When called with positive integer argument |
| #detect | Alias for Enumerable#find. |
| #drop | For positive integer |
| #drop_while | Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point: |
| #each_cons | Calls the block with each successive overlapped |
| #each_entry | Calls the given block with each element, converting multiple values from yield to an array; returns |
| #each_slice | Calls the block with each successive disjoint |
| #each_with_index | With a block given, calls the block with each element and its index; returns |
| #each_with_object | Calls the block once for each element, passing both the element and the given object: |
| #entries | Alias for Enumerable#to_a. |
| #filter | Returns an array containing elements selected by the block. |
| #filter_map | Returns an array containing truthy elements returned by the block. |
| #find | Returns the first element for which the block returns a truthy value. |
| #find_all | Alias for Enumerable#filter. |
| #find_index | Returns the index of the first element that meets a specified criterion, or |
| #first | Returns the first element or elements. |
| #flat_map | Returns an array of flattened objects returned by the block. |
| #grep | Returns an array of objects based elements of |
| #grep_v | Returns an array of objects based on elements of |
| #group_by | With a block given returns a hash: |
| #include? | Alias for Enumerable#member?. |
| #inject | Returns an object formed from operands via either: |
| #lazy | Returns an |
| #map | Returns an array of objects returned by the block. |
| #max | Returns the element with the maximum element according to a given criterion. |
| #max_by | Returns the elements for which the block returns the maximum values. |
| #member? | Returns whether for any element |
| #min | Returns the element with the minimum element according to a given criterion. |
| #min_by | Returns the elements for which the block returns the minimum values. |
| #minmax | Returns a 2-element array containing the minimum and maximum elements according to a given criterion. |
| #minmax_by | Returns a 2-element array containing the elements for which the block returns minimum and maximum values: |
| #none? | Returns whether no element meets a given criterion. |
| #one? | Returns whether exactly one element meets a given criterion. |
| #partition | With a block given, returns an array of two arrays: |
| #reduce | Alias for Enumerable#inject. |
| #reject | Returns an array of objects rejected by the block. |
| #reverse_each | With a block given, calls the block with each element, but in reverse order; returns |
| #select | Alias for Enumerable#filter. |
| #slice_after | Creates an enumerator for each chunked elements. |
| #slice_before | With argument |
| #slice_when | Creates an enumerator for each chunked elements. |
| #sort | Returns an array containing the sorted elements of |
| #sort_by | With a block given, returns an array of elements of |
| #sum | With no block given, returns the sum of |
| #take | For non-negative integer |
| #take_while | Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements up to that point: |
| #tally | Returns a hash containing the counts of equal elements: |
| #to_a | Returns an array containing the items in |
| #to_h | When |
| #to_set | Makes a set from the enumerable object with given arguments. |
| #uniq | With no block, returns a new array containing only unique elements; the array has no two elements |
| #zip | With no block given, returns a new array |
Constructor Details
.new(*member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct
.new(class_name, *member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct
Struct_subclass.new(*member_names) ⇒ Struct
Struct_subclass.new(**member_names) ⇒ Struct
Struct
.new(class_name, *member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct
Struct_subclass.new(*member_names) ⇒ Struct
Struct_subclass.new(**member_names) ⇒ 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, :) # => 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, :) # => Struct::Foo
Foo.name # => "Struct::Foo"
Foo.superclass # => Struct
Without string argument class_name, returns a new anonymous subclass of Struct:
Struct.new(:foo, :).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 new:
"The new subclass is Struct::Customer"
Member Names
::Symbol arguments member_names determines the members of the new subclass:
Struct.new(:foo, :).members # => [:foo, :bar]
Struct.new('Foo', :foo, :).members # => [:foo, :bar]
The new subclass has instance methods corresponding to member_names:
Foo = Struct.new('Foo', :foo, :)
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 new has these singleton methods:
-
Method
::newcreates 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
:inspectreturns 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, :, 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, :, 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, :, 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>
# File 'struct.c', line 642
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_RAW(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;
}
#initialize(*args)
[ GitHub ]# File 'struct.c', line 741
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 Attribute Details
StructClass.keyword_init? ⇒ Boolean (readonly)
# File 'struct.c', line 344
static VALUE
rb_struct_s_keyword_init_p(VALUE obj)
{
}
Class Method Details
StructClass.members ⇒ array_of_symbols
Returns the member names of the Struct descendant as an array:
Customer = Struct.new(:name, :address, :zip)
Customer.members # => [:name, :address, :zip]
# File 'struct.c', line 206
static VALUE
rb_struct_s_members_m(VALUE klass)
{
VALUE members = rb_struct_s_members(klass);
return rb_ary_dup(members);
}
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
# File 'struct.c', line 1399
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);
}
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.
# File 'struct.c', line 1217
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, value) ⇒ value
#[]=(n, value) ⇒ value
value
#[]=(n, value) ⇒ value
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.
# File 'struct.c', line 1255
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;
}
Alias for #to_a.
#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}
# File 'struct.c', line 1091
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;
}
Finds and returns an object among nested objects. The nested objects may be instances of various classes. See Dig Methods.
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
# File 'struct.c', line 1543
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 ⇒ Enumerator
self
#each ⇒ Enumerator
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.
# File 'struct.c', line 891
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 ⇒ Enumerator
self
#each_pair ⇒ Enumerator
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.
# File 'struct.c', line 926
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:
-
other.class == self.class. -
For each member name
name,other.name.eql?(self.name).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#==.
# File 'struct.c', line 1480
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 ⇒ Enumerator
Also known as: #select
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.
# File 'struct.c', line 1347
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 #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.
# File 'struct.c', line 1431
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)
# File 'struct.c', line 1122
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;
}
Alias for #to_s.
#length ⇒ Integer Also known as: #size
# File 'struct.c', line 1505
VALUE
rb_struct_size(VALUE s)
{
return LONG2FIX(RSTRUCT_LEN(s));
}
#members ⇒ array_of_symbols
# File 'struct.c', line 226
static VALUE
rb_struct_members_m(VALUE obj)
{
return rb_struct_s_members_m(rb_obj_class(obj));
}
#select {|value| ... } ⇒ Array
#select ⇒ Enumerator
Alias for #filter.
Alias for #length.
#to_a ⇒ Array Also known as: #values, #deconstruct
# File 'struct.c', line 1027
static VALUE
rb_struct_to_a(VALUE s)
{
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s));
}
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.
# File 'struct.c', line 1056
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_s ⇒ String Also known as: #inspect
# File 'struct.c', line 1008
static VALUE
rb_struct_inspect(VALUE s)
{
return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<struct "));
}
Alias for #to_a.
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.
# File 'struct.c', line 1323
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);
}