diff options
Diffstat (limited to 'struct.c')
| -rw-r--r-- | struct.c | 188 |
1 files changed, 111 insertions, 77 deletions
@@ -52,7 +52,8 @@ struct_ivar_get(VALUE c, ID id) RUBY_ASSERT(RB_TYPE_P(c, T_CLASS)); ivar = rb_attr_get(c, id); if (!NIL_P(ivar)) { - return rb_ivar_set(orig, id, ivar); + if (!OBJ_FROZEN(orig)) rb_ivar_set(orig, id, ivar); + return ivar; } } } @@ -82,9 +83,9 @@ rb_struct_members(VALUE s) { VALUE members = rb_struct_s_members(rb_obj_class(s)); - if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { + if (RSTRUCT_LEN_RAW(s) != RARRAY_LEN(members)) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", - RARRAY_LEN(members), RSTRUCT_LEN(s)); + RARRAY_LEN(members), RSTRUCT_LEN_RAW(s)); } return members; } @@ -136,7 +137,7 @@ struct_set_members(VALUE klass, VALUE /* frozen hidden array */ members) j = struct_member_pos_probe(j, mask); } } - OBJ_FREEZE_RAW(back); + OBJ_FREEZE(back); } rb_ivar_set(klass, id_members, members); rb_ivar_set(klass, id_back_members, back); @@ -160,10 +161,10 @@ struct_member_pos(VALUE s, VALUE name) mask = RARRAY_LEN(back); if (mask <= AREF_HASH_THRESHOLD) { - if (UNLIKELY(RSTRUCT_LEN(s) != mask)) { + if (UNLIKELY(RSTRUCT_LEN_RAW(s) != mask)) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", - mask, RSTRUCT_LEN(s)); + mask, RSTRUCT_LEN_RAW(s)); } for (j = 0; j < mask; j++) { if (RARRAY_AREF(back, j) == name) @@ -172,9 +173,9 @@ struct_member_pos(VALUE s, VALUE name) return -1; } - if (UNLIKELY(RSTRUCT_LEN(s) != FIX2INT(RARRAY_AREF(back, mask-1)))) { + if (UNLIKELY(RSTRUCT_LEN_RAW(s) != FIX2INT(RARRAY_AREF(back, mask-1)))) { rb_raise(rb_eTypeError, "struct size differs (%d required %ld given)", - FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN(s)); + FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN_RAW(s)); } mask -= 3; @@ -234,9 +235,9 @@ rb_struct_getmember(VALUE obj, ID id) VALUE slot = ID2SYM(id); int i = struct_member_pos(obj, slot); if (i != -1) { - return RSTRUCT_GET(obj, i); + return RSTRUCT_GET_RAW(obj, i); } - rb_name_err_raise("`%1$s' is not a struct member", obj, ID2SYM(id)); + rb_name_err_raise("'%1$s' is not a struct member", obj, ID2SYM(id)); UNREACHABLE_RETURN(Qnil); } @@ -273,7 +274,7 @@ new_struct(VALUE name, VALUE super) rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name); rb_mod_remove_const(super, ID2SYM(id)); } - return rb_define_class_id_under(super, id, super); + return rb_define_class_id_under_no_pin(super, id, super); } NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx)); @@ -422,7 +423,7 @@ struct_make_members_list(va_list ar) } ary = rb_hash_keys(list); RBASIC_CLEAR_CLASS(ary); - OBJ_FREEZE_RAW(ary); + OBJ_FREEZE(ary); return ary; } @@ -491,8 +492,13 @@ rb_struct_define(const char *name, ...) ary = struct_make_members_list(ar); va_end(ar); - if (!name) st = anonymous_struct(rb_cStruct); - else st = new_struct(rb_str_new2(name), rb_cStruct); + if (!name) { + st = anonymous_struct(rb_cStruct); + } + else { + st = new_struct(rb_str_new2(name), rb_cStruct); + rb_vm_register_global_object(st); + } return setup_struct(st, ary); } @@ -506,7 +512,7 @@ rb_struct_define_under(VALUE outer, const char *name, ...) ary = struct_make_members_list(ar); va_end(ar); - return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary); + return setup_struct(rb_define_class_id_under(outer, rb_intern(name), rb_cStruct), ary); } /* @@ -527,7 +533,7 @@ rb_struct_define_under(VALUE outer, const char *name, ...) * Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo * f = Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1> * - * <b>\Class Name</b> + * <b>Class Name</b> * * With string argument +class_name+, * returns a new subclass of +Struct+ named <tt>Struct::<em>class_name</em></tt>: @@ -582,7 +588,7 @@ rb_struct_define_under(VALUE outer, const char *name, ...) * * A subclass returned by Struct.new has these singleton methods: * - * - \Method <tt>::new </tt> creates an instance of the subclass: + * - Method <tt>::new </tt> 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> @@ -595,12 +601,12 @@ rb_struct_define_under(VALUE outer, const char *name, ...) * Foo.new(foo: 0, bar: 1, baz: 2) * # Raises ArgumentError: unknown keywords: baz * - * - \Method <tt>:inspect</tt> returns a string representation of the subclass: + * - Method <tt>:inspect</tt> returns a string representation of the subclass: * * Foo.inspect * # => "Struct::Foo" * - * - \Method <tt>::members</tt> returns an array of the member names: + * - Method <tt>::members</tt> returns an array of the member names: * * Foo.members # => [:foo, :bar] * @@ -677,7 +683,7 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass) } rest = rb_hash_keys(rest); RBASIC_CLEAR_CLASS(rest); - OBJ_FREEZE_RAW(rest); + OBJ_FREEZE(rest); if (NIL_P(name)) { st = anonymous_struct(klass); } @@ -727,7 +733,7 @@ struct_hash_set_i(VALUE key, VALUE val, VALUE arg) } else { rb_struct_modify(args->self); - RSTRUCT_SET(args->self, i, val); + RSTRUCT_SET_RAW(args->self, i, val); } return ST_CONTINUE; } @@ -776,7 +782,7 @@ rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self) rb_raise(rb_eArgError, "struct size differs"); } for (long i=0; i<argc; i++) { - RSTRUCT_SET(self, i, argv[i]); + RSTRUCT_SET_RAW(self, i, argv[i]); } if (n > argc) { rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc); @@ -789,7 +795,7 @@ VALUE rb_struct_initialize(VALUE self, VALUE values) { rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self); - if (rb_obj_is_kind_of(self, rb_cData)) OBJ_FREEZE_RAW(self); + if (rb_obj_is_kind_of(self, rb_cData)) OBJ_FREEZE(self); RB_GC_GUARD(values); return Qnil; } @@ -805,12 +811,31 @@ struct_alloc(VALUE klass) { long n = num_members(klass); size_t embedded_size = offsetof(struct RStruct, as.ary) + (sizeof(VALUE) * n); + if (RCLASS_MAX_IV_COUNT(klass) > 0) { + embedded_size += sizeof(VALUE); + } + VALUE flags = T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0); if (n > 0 && rb_gc_size_allocatable_p(embedded_size)) { flags |= n << RSTRUCT_EMBED_LEN_SHIFT; + if (RCLASS_MAX_IV_COUNT(klass) == 0) { + // We set the flag before calling `NEWOBJ_OF` in case a NEWOBJ tracepoint does + // attempt to write fields. We'll remove it later if no fields was written to. + flags |= RSTRUCT_GEN_FIELDS; + } NEWOBJ_OF(st, struct RStruct, klass, flags, embedded_size, 0); + if (RCLASS_MAX_IV_COUNT(klass) == 0) { + if (!rb_shape_obj_has_fields((VALUE)st) + && embedded_size < rb_gc_obj_slot_size((VALUE)st)) { + FL_UNSET_RAW((VALUE)st, RSTRUCT_GEN_FIELDS); + RSTRUCT_SET_FIELDS_OBJ((VALUE)st, 0); + } + } + else { + RSTRUCT_SET_FIELDS_OBJ((VALUE)st, 0); + } rb_mem_clear((VALUE *)st->as.ary, n); @@ -819,6 +844,10 @@ struct_alloc(VALUE klass) else { NEWOBJ_OF(st, struct RStruct, klass, flags, sizeof(struct RStruct), 0); + st->as.heap.ptr = NULL; + st->as.heap.fields_obj = 0; + st->as.heap.len = 0; + st->as.heap.ptr = struct_heap_alloc((VALUE)st, n); rb_mem_clear((VALUE *)st->as.heap.ptr, n); st->as.heap.len = n; @@ -888,8 +917,8 @@ 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)); + for (i=0; i<RSTRUCT_LEN_RAW(s); i++) { + rb_yield(RSTRUCT_GET_RAW(s, i)); } return s; } @@ -926,16 +955,16 @@ rb_struct_each_pair(VALUE s) 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++) { + for (i=0; i<RSTRUCT_LEN_RAW(s); i++) { VALUE key = rb_ary_entry(members, i); - VALUE value = RSTRUCT_GET(s, i); + VALUE value = RSTRUCT_GET_RAW(s, i); rb_yield_values(2, key, value); } } else { - for (i=0; i<RSTRUCT_LEN(s); i++) { + for (i=0; i<RSTRUCT_LEN_RAW(s); i++) { VALUE key = rb_ary_entry(members, i); - VALUE value = RSTRUCT_GET(s, i); + VALUE value = RSTRUCT_GET_RAW(s, i); rb_yield(rb_assoc_new(key, value)); } } @@ -952,6 +981,7 @@ inspect_struct(VALUE s, VALUE prefix, int recur) char first = RSTRING_PTR(cname)[0]; if (recur || first != '#') { + rb_str_cat2(str, " "); rb_str_append(str, cname); } if (recur) { @@ -959,7 +989,7 @@ inspect_struct(VALUE s, VALUE prefix, int recur) } members = rb_struct_members(s); - len = RSTRUCT_LEN(s); + len = RSTRUCT_LEN_RAW(s); for (i=0; i<len; i++) { VALUE slot; @@ -968,7 +998,7 @@ inspect_struct(VALUE s, VALUE prefix, int recur) if (i > 0) { rb_str_cat2(str, ", "); } - else if (first != '#') { + else { rb_str_cat2(str, " "); } slot = RARRAY_AREF(members, i); @@ -980,7 +1010,7 @@ inspect_struct(VALUE s, VALUE prefix, int recur) rb_str_append(str, rb_inspect(slot)); } rb_str_cat2(str, "="); - rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i))); + rb_str_append(str, rb_inspect(RSTRUCT_GET_RAW(s, i))); } rb_str_cat2(str, ">"); @@ -1002,7 +1032,7 @@ inspect_struct(VALUE s, VALUE prefix, int recur) static VALUE rb_struct_inspect(VALUE s) { - return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<struct ")); + return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<struct")); } /* @@ -1021,7 +1051,7 @@ rb_struct_inspect(VALUE s) static VALUE rb_struct_to_a(VALUE s) { - return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s)); + return rb_ary_new4(RSTRUCT_LEN_RAW(s), RSTRUCT_CONST_PTR(s)); } /* @@ -1050,13 +1080,13 @@ rb_struct_to_a(VALUE s) static VALUE rb_struct_to_h(VALUE s) { - VALUE h = rb_hash_new_with_size(RSTRUCT_LEN(s)); + VALUE h = rb_hash_new_with_size(RSTRUCT_LEN_RAW(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); + for (i=0; i<RSTRUCT_LEN_RAW(s); i++) { + VALUE k = rb_ary_entry(members, i), v = RSTRUCT_GET_RAW(s, i); if (block_given) rb_hash_set_pair(h, rb_yield_values(2, k, v)); else @@ -1097,7 +1127,7 @@ rb_struct_deconstruct_keys(VALUE s, VALUE keys) rb_obj_class(keys)); } - if (RSTRUCT_LEN(s) < RARRAY_LEN(keys)) { + if (RSTRUCT_LEN_RAW(s) < RARRAY_LEN(keys)) { return rb_hash_new_with_size(0); } h = rb_hash_new_with_size(RARRAY_LEN(keys)); @@ -1107,7 +1137,7 @@ rb_struct_deconstruct_keys(VALUE s, VALUE keys) if (i < 0) { return h; } - rb_hash_aset(h, key, RSTRUCT_GET(s, i)); + rb_hash_aset(h, key, RSTRUCT_GET_RAW(s, i)); } return h; } @@ -1119,12 +1149,12 @@ 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)) { + if (RSTRUCT_LEN_RAW(copy) != RSTRUCT_LEN_RAW(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)); + for (i=0, len=RSTRUCT_LEN_RAW(copy); i<len; i++) { + RSTRUCT_SET_RAW(copy, i, RSTRUCT_GET_RAW(s, i)); } return copy; @@ -1147,7 +1177,7 @@ rb_struct_pos(VALUE s, VALUE *name) else { long len; i = NUM2LONG(idx); - len = RSTRUCT_LEN(s); + len = RSTRUCT_LEN_RAW(s); if (i < 0) { if (i + len < 0) { *name = LONG2FIX(i); @@ -1167,7 +1197,7 @@ static void invalid_struct_pos(VALUE s, VALUE idx) { if (FIXNUM_P(idx)) { - long i = FIX2INT(idx), len = RSTRUCT_LEN(s); + long i = FIX2INT(idx), len = RSTRUCT_LEN_RAW(s); if (i < 0) { rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, len); @@ -1213,7 +1243,7 @@ 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); + return RSTRUCT_GET_RAW(s, i); } /* @@ -1252,7 +1282,7 @@ 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); + RSTRUCT_SET_RAW(s, i, val); return val; } @@ -1270,7 +1300,7 @@ rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound) { int i = rb_struct_pos(s, &idx); if (i < 0) return notfound; - return RSTRUCT_GET(s, i); + return RSTRUCT_GET_RAW(s, i); } static VALUE @@ -1317,7 +1347,7 @@ struct_entry(VALUE s, long n) 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); + return rb_get_values_at(s, RSTRUCT_LEN_RAW(s), argc, argv, struct_entry); } /* @@ -1347,9 +1377,9 @@ rb_struct_select(int argc, VALUE *argv, VALUE s) 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)); + for (i = 0; i < RSTRUCT_LEN_RAW(s); i++) { + if (RTEST(rb_yield(RSTRUCT_GET_RAW(s, i)))) { + rb_ary_push(result, RSTRUCT_GET_RAW(s, i)); } } @@ -1362,9 +1392,9 @@ recursive_equal(VALUE s, VALUE s2, int recur) long i, len; if (recur) return Qtrue; /* Subtle! */ - len = RSTRUCT_LEN(s); + len = RSTRUCT_LEN_RAW(s); for (i=0; i<len; i++) { - if (!rb_equal(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse; + if (!rb_equal(RSTRUCT_GET_RAW(s, i), RSTRUCT_GET_RAW(s2, i))) return Qfalse; } return Qtrue; } @@ -1374,7 +1404,7 @@ recursive_equal(VALUE s, VALUE s2, int recur) * call-seq: * self == other -> true or false * - * Returns +true+ if and only if the following are true; otherwise returns +false+: + * Returns whether both the following are true: * * - <tt>other.class == self.class</tt>. * - For each member name +name+, <tt>other.name == self.name</tt>. @@ -1396,7 +1426,7 @@ 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)) { + if (RSTRUCT_LEN_RAW(s) != RSTRUCT_LEN_RAW(s2)) { rb_bug("inconsistent struct"); /* should never happen */ } @@ -1430,9 +1460,9 @@ rb_struct_hash(VALUE s) VALUE n; h = rb_hash_start(rb_hash(rb_obj_class(s))); - len = RSTRUCT_LEN(s); + len = RSTRUCT_LEN_RAW(s); for (i = 0; i < len; i++) { - n = rb_hash(RSTRUCT_GET(s, i)); + n = rb_hash(RSTRUCT_GET_RAW(s, i)); h = rb_hash_uint(h, NUM2LONG(n)); } h = rb_hash_end(h); @@ -1445,9 +1475,9 @@ recursive_eql(VALUE s, VALUE s2, int recur) long i, len; if (recur) return Qtrue; /* Subtle! */ - len = RSTRUCT_LEN(s); + len = RSTRUCT_LEN_RAW(s); for (i=0; i<len; i++) { - if (!rb_eql(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse; + if (!rb_eql(RSTRUCT_GET_RAW(s, i), RSTRUCT_GET_RAW(s2, i))) return Qfalse; } return Qtrue; } @@ -1477,7 +1507,7 @@ 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)) { + if (RSTRUCT_LEN_RAW(s) != RSTRUCT_LEN_RAW(s2)) { rb_bug("inconsistent struct"); /* should never happen */ } @@ -1499,7 +1529,7 @@ rb_struct_eql(VALUE s, VALUE s2) VALUE rb_struct_size(VALUE s) { - return LONG2FIX(RSTRUCT_LEN(s)); + return LONG2FIX(RSTRUCT_LEN_RAW(s)); } /* @@ -1547,7 +1577,7 @@ rb_struct_dig(int argc, VALUE *argv, VALUE self) /* * Document-class: Data * - * \Class \Data provides a convenient way to define simple classes + * Class \Data provides a convenient way to define simple classes * for value-alike objects. * * The simplest example of usage: @@ -1635,7 +1665,7 @@ rb_struct_dig(int argc, VALUE *argv, VALUE self) * * * Note that member-less \Data is acceptable and might be a useful technique - * for defining several homogenous data classes, like + * for defining several homogeneous data classes, like * * class HTTPFetcher * Response = Data.define(:body) @@ -1680,7 +1710,7 @@ rb_data_s_def(int argc, VALUE *argv, VALUE klass) } rest = rb_hash_keys(rest); RBASIC_CLEAR_CLASS(rest); - OBJ_FREEZE_RAW(rest); + OBJ_FREEZE(rest); data_class = anonymous_struct(klass); setup_data(data_class, rest); if (rb_block_given_p()) { @@ -1699,7 +1729,9 @@ rb_data_define(VALUE super, ...) ary = struct_make_members_list(ar); va_end(ar); if (!super) super = rb_cData; - return setup_data(anonymous_struct(super), ary); + VALUE klass = setup_data(anonymous_struct(super), ary); + rb_vm_register_global_object(klass); + return klass; } /* @@ -1752,7 +1784,8 @@ rb_data_define(VALUE super, ...) * important for redefining initialize in order to convert arguments or provide * defaults: * - * Measure = Data.define(:amount, :unit) do + * Measure = Data.define(:amount, :unit) + * class Measure * NONE = Data.define * * def initialize(amount:, unit: NONE.new) @@ -1761,7 +1794,7 @@ rb_data_define(VALUE super, ...) * end * * Measure.new('10', 'km') # => #<data Measure amount=10.0, unit="km"> - * Measure.new(10_000) # => #<data Measure amount=10000.0, unit=#<data NONE>> + * Measure.new(10_000) # => #<data Measure amount=10000.0, unit=#<data Measure::NONE>> * */ @@ -1777,6 +1810,7 @@ rb_data_initialize_m(int argc, const VALUE *argv, VALUE self) if (num_members > 0) { rb_exc_raise(rb_keyword_error_new("missing", members)); } + OBJ_FREEZE(self); return Qnil; } if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) { @@ -1795,7 +1829,7 @@ rb_data_initialize_m(int argc, const VALUE *argv, VALUE self) rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg); // Freeze early before potentially raising, so that we don't leave an // unfrozen copy on the heap, which could get exposed via ObjectSpace. - OBJ_FREEZE_RAW(self); + OBJ_FREEZE(self); if (arg.unknown_keywords != Qnil) { rb_exc_raise(rb_keyword_error_new("unknown", arg.unknown_keywords)); } @@ -1807,7 +1841,7 @@ static VALUE rb_data_init_copy(VALUE copy, VALUE s) { copy = rb_struct_init_copy(copy, s); - RB_OBJ_FREEZE_RAW(copy); + RB_OBJ_FREEZE(copy); return copy; } @@ -1877,14 +1911,14 @@ rb_data_with(int argc, const VALUE *argv, VALUE self) static VALUE rb_data_inspect(VALUE s) { - return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<data ")); + return rb_exec_recursive(inspect_struct, s, rb_str_new2("#<data")); } /* * call-seq: * self == other -> true or false * - * Returns +true+ if +other+ is the same class as +self+, and all members are + * Returns whether +other+ is the same class as +self+, and all members are * equal. * * Examples: @@ -2058,7 +2092,7 @@ rb_data_inspect(VALUE s) /* * Document-class: Struct * - * \Class \Struct provides a convenient way to create a simple class + * Class \Struct provides a convenient way to create a simple class * that can store and fetch values. * * This example creates a subclass of +Struct+, <tt>Struct::Customer</tt>; @@ -2098,7 +2132,7 @@ rb_data_inspect(VALUE s) * * == What's Here * - * First, what's elsewhere. \Class \Struct: + * First, what's elsewhere. Class \Struct: * * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here]. * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here], @@ -2124,7 +2158,7 @@ rb_data_inspect(VALUE s) * === Methods for Querying * * - #hash: Returns the integer hash code. - * - #length, #size: Returns the number of members. + * - #size (aliased as #length): Returns the number of members. * * === Methods for Comparing * @@ -2136,13 +2170,13 @@ rb_data_inspect(VALUE s) * === 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. + * - #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, #filter: Returns an array of member values from +self+, + * - #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. * @@ -2157,7 +2191,7 @@ rb_data_inspect(VALUE s) * * === Methods for Converting * - * - #inspect, #to_s: Returns a string representation of +self+. + * - #inspect (aliased as #to_s): Returns a string representation of +self+. * - #to_h: Returns a hash of the member name/value pairs in +self+. * */ |
