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:
-
Creating a Subclass
-
Querying
-
Comparing
-
Fetching
-
Assigning
-
Iterating
-
Converting
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
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, #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
true
if the class was initialized withkeyword_init: true
.
Class Method Summary
-
StructClass.members ⇒ array_of_symbols
Returns the member names of the
Struct
descendant as an array: -
.new(*member_names, keyword_init: nil) {|Struct_subclass| ... } ⇒ Struct
constructor
new
returns a new subclass ofStruct
.
Instance Method Summary
-
#==(other) ⇒ Boolean
Returns
true
if 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
true
if and only if the following are true; otherwise returnsfalse
: -
#select {|value| ... } ⇒ Array
(also: #select)
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) 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
self
as an array: -
#select {|value| ... } ⇒ Array
Alias for #filter.
-
#size ⇒ Integer
Alias for #length.
-
#to_a ⇒ Array
(also: #values, #deconstruct)
Returns the values in
self
as 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
::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, :, 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 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_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 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 Attribute Details
StructClass.keyword_init? ⇒ Boolean
(readonly)
# File 'struct.c', line 343
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 205
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 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); }
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 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, 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 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; }
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 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; }
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 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 ⇒ 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 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 ⇒ 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 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
:
-
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 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 ⇒ 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 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 #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 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)
# 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; }
Alias for #to_s.
#length ⇒ Integer Also known as: #size
# File 'struct.c', line 1504
VALUE rb_struct_size(VALUE s) { return LONG2FIX(RSTRUCT_LEN(s)); }
#members ⇒ array_of_symbols
# 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 ⇒ Enumerator
Alias for #filter.
Alias for #length.
#to_a ⇒ Array Also known as: #values, #deconstruct
# File 'struct.c', line 1026
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 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_s ⇒ String Also known as: #inspect
# File 'struct.c', line 1007
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 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); }