Class: Struct

Inherits:
Object show all
Includes:
Enumerable
Defined in:
struct.c

Overview

A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.

The Struct class is a generator of specific classes, each one of which is defined to hold a set of variables and their accessors. In these examples, we'll call the generated class "CustomerClass,'' and we'll show an example instance of that class as "CustomerInst.''

In the descriptions that follow, the parameter symbol refers to a symbol, which is either a quoted string or a Symbol (such as :name).

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#all?, #any?, #chunk, #collect, #collect_concat, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #find, #find_all, #find_index, #first, #flat_map, #grep, #group_by, #include?, #inject, #lazy, #map, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #slice_before, #sort, #sort_by, #take, #take_while, #zip

Constructor Details

#initializeObject


368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'struct.c', line 368

static VALUE
rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
{
    VALUE klass = rb_obj_class(self);
    long n;

    rb_struct_modify(self);
    n = num_members(klass);
    if (n < argc) {
	rb_raise(rb_eArgError, "struct size differs");
    }
    MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
    if (n > argc) {
	rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
    }
    return Qnil;
}

Class Method Details

.new([aString][, aSym]) ⇒ StructClass .new([aString][, aSym]) {|StructClass| ... } ⇒ StructClass .new(arg, ...) ⇒ Object .[](arg, ...) ⇒ Object

Creates a new class, named by aString, containing accessor methods for the given symbols. If the name aString is omitted, an anonymous structure class will be created. Otherwise, the name of this struct will appear as a constant in class Struct, so it must be unique for all Structs in the system and should start with a capital letter. Assigning a structure class to a constant effectively gives the class the name of the constant.

If a block is given, it will be evaluated in the context of StructClass, passing StructClass as a parameter.

Customer = Struct.new(:name, :address) do
  def greeting
    "Hello #{name}!"
  end
end
Customer.new("Dave", "123 Main").greeting  # => "Hello Dave!"

Struct::new returns a new Class object, which can then be used to create specific instances of the new structure. The number of actual parameters must be less than or equal to the number of attributes defined for this class; unset parameters default to nil. Passing too many parameters will raise an ArgumentError.

The remaining methods listed in this section (class and instance) are defined for this generated class.

# Create a structure with a name in Struct
Struct.new("Customer", :name, :address)    #=> Struct::Customer
Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">

# Create a structure named by its constant
Customer = Struct.new(:name, :address)     #=> Customer
Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">

Overloads:

  • .new([aString][, aSym]) ⇒ StructClass

    Returns:

    • (StructClass)
  • .new([aString][, aSym]) {|StructClass| ... } ⇒ StructClass

    Yields:

    • (StructClass)

    Returns:

    • (StructClass)
  • .new(arg, ...) ⇒ Object

    Returns:

  • .[](arg, ...) ⇒ Object

    Returns:


329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'struct.c', line 329

static VALUE
rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
{
    VALUE name, rest;
    long i;
    VALUE st;
    ID id;

    rb_scan_args(argc, argv, "1*", &name, &rest);
    if (!NIL_P(name) && SYMBOL_P(name)) {
	rb_ary_unshift(rest, name);
	name = Qnil;
    }
    for (i=0; i<RARRAY_LEN(rest); i++) {
	id = rb_to_id(RARRAY_PTR(rest)[i]);
	RARRAY_PTR(rest)[i] = ID2SYM(id);
    }
    st = make_struct(name, rest, klass);
    if (rb_block_given_p()) {
	rb_mod_module_eval(0, 0, st);
    }

    return st;
}

Instance Method Details

#==(other_struct) ⇒ Boolean

Equality---Returns true if other_struct is equal to this one: they must be of the same class as generated by Struct::new, and the values of all instance variables must be equal (according to Object#==).

Customer = Struct.new(:name, :address, :zip)
joe   = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
jane  = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
joe == joejr   #=> true
joe == jane    #=> false

Returns:

  • (Boolean)

854
855
856
857
858
859
860
861
862
863
864
865
# File 'struct.c', line 854

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);
}

#[](symbol) ⇒ Object #[](fixnum) ⇒ Object

Attribute Reference---Returns the value of the instance variable named by symbol, or indexed (0..length-1) by fixnum. Will raise NameError if the named variable does not exist, or IndexError if the index is out of range.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe["name"]   #=> "Joe Smith"
joe[:name]    #=> "Joe Smith"
joe[0]        #=> "Joe Smith"

Overloads:


670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'struct.c', line 670

VALUE
rb_struct_aref(VALUE s, VALUE idx)
{
    long i;

    if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) {
	return rb_struct_aref_id(s, rb_to_id(idx));
    }

    i = NUM2LONG(idx);
    if (i < 0) i = RSTRUCT_LEN(s) + i;
    if (i < 0)
        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
		 i, RSTRUCT_LEN(s));
    if (RSTRUCT_LEN(s) <= i)
        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
		 i, RSTRUCT_LEN(s));
    return RSTRUCT_PTR(s)[i];
}

#[]=(symbol) ⇒ Object #[]=(fixnum) ⇒ Object

Attribute Assignment---Assigns to the instance variable named by symbol or fixnum the value obj and returns it. Will raise a NameError if the named variable does not exist, or an IndexError if the index is out of range.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe["name"] = "Luke"
joe[:zip]   = "90210"

joe.name   #=> "Luke"
joe.zip    #=> "90210"

Overloads:


737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
# File 'struct.c', line 737

VALUE
rb_struct_aset(VALUE s, VALUE idx, VALUE val)
{
    long i;

    if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) {
	return rb_struct_aset_id(s, rb_to_id(idx), val);
    }

    i = NUM2LONG(idx);
    if (i < 0) i = RSTRUCT_LEN(s) + i;
    if (i < 0) {
        rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
		 i, RSTRUCT_LEN(s));
    }
    if (RSTRUCT_LEN(s) <= i) {
        rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
		 i, RSTRUCT_LEN(s));
    }
    rb_struct_modify(s);
    return RSTRUCT_PTR(s)[i] = val;
}

#each {|obj| ... } ⇒ Object #eachObject

Calls block once for each instance variable, passing the value as a parameter.

If no block is given, an enumerator is returned instead.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each {|x| puts(x) }

produces:

Joe Smith
123 Maple, Anytown NC
12345

Overloads:

  • #each {|obj| ... } ⇒ Object

    Yields:

    • (obj)

465
466
467
468
469
470
471
472
473
474
475
# File 'struct.c', line 465

static VALUE
rb_struct_each(VALUE s)
{
    long i;

    RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
    for (i=0; i<RSTRUCT_LEN(s); i++) {
	rb_yield(RSTRUCT_PTR(s)[i]);
    }
    return s;
}

#each_pair {|sym, obj| ... } ⇒ Object #each_pairObject

Calls block once for each instance variable, passing the name (as a symbol) and the value as parameters.

If no block is given, an enumerator is returned instead.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.each_pair {|name, value| puts("#{name} => #{value}") }

produces:

name => Joe Smith
address => 123 Maple, Anytown NC
zip => 12345

Overloads:

  • #each_pair {|sym, obj| ... } ⇒ Object

    Yields:

    • (sym, obj)

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'struct.c', line 498

static VALUE
rb_struct_each_pair(VALUE s)
{
    VALUE members;
    long i;

    RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
    members = rb_struct_members(s);
    for (i=0; i<RSTRUCT_LEN(s); i++) {
	VALUE key = rb_ary_entry(members, i);
	VALUE value = RSTRUCT_PTR(s)[i];
	rb_yield(rb_assoc_new(key, value));
    }
    return s;
}

#eql?(other) ⇒ Boolean

Two structures are equal if they are the same object, or if all their fields are equal (using eql?).

Returns:

  • (Boolean)

Returns:

  • (Boolean)

924
925
926
927
928
929
930
931
932
933
934
935
# File 'struct.c', line 924

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);
}

#hashFixnum

Return a hash value based on this struct's contents.

Returns:


894
895
896
897
898
# File 'struct.c', line 894

static VALUE
rb_struct_hash(VALUE s)
{
    return rb_exec_recursive_outer(recursive_hash, s, 0);
}

#initialize_copyObject

:nodoc:


619
620
621
622
623
624
625
626
627
628
629
# File 'struct.c', line 619

VALUE
rb_struct_init_copy(VALUE copy, VALUE s)
{
    if (!OBJ_INIT_COPY(copy, s)) return copy;
    if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
	rb_raise(rb_eTypeError, "struct size mismatch");
    }
    MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));

    return copy;
}

#to_sString #inspectString Also known as: to_s

Describe the contents of this struct in a string.

Overloads:


569
570
571
572
573
# File 'struct.c', line 569

static VALUE
rb_struct_inspect(VALUE s)
{
    return rb_exec_recursive(inspect_struct, s, 0);
}

#lengthFixnum #sizeFixnum

Returns the number of instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.length   #=> 3

Overloads:


949
950
951
952
953
# File 'struct.c', line 949

static VALUE
rb_struct_size(VALUE s)
{
    return LONG2FIX(RSTRUCT_LEN(s));
}

#membersArray

Returns an array of symbols representing the names of the instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.members   #=> [:name, :address, :zip]

Returns:


84
85
86
87
88
# File 'struct.c', line 84

static VALUE
rb_struct_members_m(VALUE obj)
{
    return rb_struct_s_members_m(rb_obj_class(obj));
}

#select {|i| ... } ⇒ Array #selectObject

Invokes the block passing in successive elements from struct, returning an array containing those elements for which the block returns a true value (equivalent to Enumerable#select).

Lots = Struct.new(:a, :b, :c, :d, :e, :f)
l = Lots.new(11, 22, 33, 44, 55, 66)
l.select {|v| (v % 2).zero? }   #=> [22, 44, 66]

Overloads:

  • #select {|i| ... } ⇒ Array

    Yields:

    • (i)

    Returns:


803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
# File 'struct.c', line 803

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, rb_struct_size);
    result = rb_ary_new();
    for (i = 0; i < RSTRUCT_LEN(s); i++) {
	if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
	    rb_ary_push(result, RSTRUCT_PTR(s)[i]);
	}
    }

    return result;
}

#lengthFixnum #sizeFixnum

Returns the number of instance variables.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.length   #=> 3

Overloads:


949
950
951
952
953
# File 'struct.c', line 949

static VALUE
rb_struct_size(VALUE s)
{
    return LONG2FIX(RSTRUCT_LEN(s));
}

#to_aArray #valuesArray

Returns the values for this instance as an array.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_a[1]   #=> "123 Maple, Anytown NC"

Overloads:


587
588
589
590
591
# File 'struct.c', line 587

static VALUE
rb_struct_to_a(VALUE s)
{
    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
}

#to_hHash

Returns the values for this instance as a hash with keys corresponding to the instance variable name.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_h[:address]   #=> "123 Maple, Anytown NC"

Returns:


605
606
607
608
609
610
611
612
613
614
615
616
# File 'struct.c', line 605

static VALUE
rb_struct_to_h(VALUE s)
{
    VALUE h = rb_hash_new();
    VALUE members = rb_struct_members(s);
    long i;

    for (i=0; i<RSTRUCT_LEN(s); i++) {
	rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
    }
    return h;
}

#to_aArray #valuesArray

Returns the values for this instance as an array.

Customer = Struct.new(:name, :address, :zip)
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe.to_a[1]   #=> "123 Maple, Anytown NC"

Overloads:


587
588
589
590
591
# File 'struct.c', line 587

static VALUE
rb_struct_to_a(VALUE s)
{
    return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
}

#values_at(selector, ...) ⇒ Array

Returns an array containing the elements in

+self+ corresponding to the given selector(s). The selectors
may be either integer indices or ranges.
See also </code>.select<code>.

   a = %w{ a b c d e f }
   a.values_at(1, 3, 5)
   a.values_at(1, 3, 5, 7)
   a.values_at(-1, -3, -5, -7)
   a.values_at(1..3, 2...5)

Returns:


782
783
784
785
786
# File 'struct.c', line 782

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);
}