From 19d3bb2d90f9806ea6cdef97a139de9f2050363a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 20 Sep 2018 12:02:35 +0900 Subject: Make `#to_h` to take a block; [ruby-core:89088] --- mrbgems/mruby-array-ext/mrblib/array.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index c0995bb99..bb9e61bdd 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -932,4 +932,29 @@ class Array self.map { |row| row[column_index] } end end + + ## + # call-seq: + # ary.to_h -> Hash + # ary.to_h{|item| ... } -> Hash + # + # Returns the result of interpreting aray as an array of + # [key, value] pairs. If a block is given, it should + # return [key, value] pairs to construct a hash. + # + # [[:foo, :bar], [1, 2]].to_h + # # => {:foo => :bar, 1 => 2} + # [1, 2].to_h{|x| [x, x*2]} + # # => {1 => 2, 2 => 4} + # + def to_h(&blk) + h = {} + self.each do |v| + v = blk.call(v) if blk + raise TypeError, "wrong element type #{v.class}" unless Array === v + raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2 + h[v[0]] = v[1] + end + h + end end -- cgit v1.2.3 From dd346be99aaf6d0220f067c78decb29548c7dfe6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 20 Sep 2018 23:56:53 +0900 Subject: Improve performance of `Array#uniq!`. --- mrbgems/mruby-array-ext/mrblib/array.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index bb9e61bdd..4f676a121 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -41,19 +41,22 @@ class Array # c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]] # def uniq!(&block) - ary = self.dup - result = [] if block hash = {} - while ary.size > 0 - val = ary.shift + self.each do |val| key = block.call(val) - hash[key] = val unless hash.has_key?(key) + hash[key] = val unless hash.key?(key) end - hash.each_value do |value| - result << value + result = hash.values + elsif self.size > 20 + hash = {} + self.each do |val| + hash[val] = val end + result = hash.values else + ary = self.dup + result = [] while ary.size > 0 result << ary.shift ary.delete(result.last) -- cgit v1.2.3 From f23f2bbdad7a15bec8812b029cb23c2117d7c63c Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 21 Sep 2018 00:01:48 +0900 Subject: Implement `Array#union` which is introduced in Ruby2.6. --- mrbgems/mruby-array-ext/mrblib/array.rb | 19 +++++++++++++++++++ mrbgems/mruby-array-ext/test/array.rb | 8 ++++++++ 2 files changed, 27 insertions(+) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 4f676a121..8c2acc7ac 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -137,6 +137,25 @@ class Array ary.uniq! or ary end + ## + # call-seq: + # ary.union(other_ary,...) -> new_ary + # + # Set Union---Returns a new array by joining this array with + # other_ary, removing duplicates. + # + # ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"]) + # #=> ["a", "b", "c", "d", "e"] + # + def union(*args) + ary = self.dup + args.each_with_index do |x,i| + ary.concat(x) + ary.uniq! if i % 20 == 0 + end + ary.uniq! or ary + end + ## # call-seq: # ary & other_ary -> new_ary diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 4f54c65c3..84f9cfeaf 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -75,6 +75,14 @@ assert("Array#|") do assert_equal [1, 2, 3, 1], a end +assert("Array#union") do + a = [1, 2, 3, 1] + b = [1, 4] + c = [1, 5] + + assert_equal [1, 2, 3, 4, 5], a.union(b,c) +end + assert("Array#&") do a = [1, 2, 3, 1] b = [1, 4] -- cgit v1.2.3 From d78acc7afed35813f25e3091150dab668c373f05 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 26 Sep 2018 11:14:36 +0900 Subject: Add index to larger segment lists for performance --- mrbgems/mruby-array-ext/mrblib/array.rb | 14 +- mrblib/hash.rb | 2 +- src/hash.c | 440 +++++++++++++++++++++++--------- 3 files changed, 329 insertions(+), 127 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 8c2acc7ac..eac8d4718 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -1,3 +1,4 @@ +# coding: cp932 class Array ## # call-seq: @@ -41,26 +42,19 @@ class Array # c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]] # def uniq!(&block) + hash = {} if block - hash = {} self.each do |val| key = block.call(val) hash[key] = val unless hash.key?(key) end result = hash.values - elsif self.size > 20 + else hash = {} self.each do |val| hash[val] = val end - result = hash.values - else - ary = self.dup - result = [] - while ary.size > 0 - result << ary.shift - ary.delete(result.last) - end + result = hash.keys end if result.size == self.size nil diff --git a/mrblib/hash.rb b/mrblib/hash.rb index eba92ba4a..245b76ee0 100644 --- a/mrblib/hash.rb +++ b/mrblib/hash.rb @@ -334,7 +334,7 @@ class Hash # h["AA"] #=> "b" # def rehash - self.size + # do nothing (for now) self end end diff --git a/src/hash.c b/src/hash.c index 820ee5a71..07a12be68 100644 --- a/src/hash.c +++ b/src/hash.c @@ -16,14 +16,48 @@ mrb_int mrb_float_id(mrb_float f); #endif -static inline khint_t -mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) +/* return non zero to break the loop */ +typedef int (sg_foreach_func)(mrb_state *mrb,mrb_value key, mrb_value val, void *data); + +#ifndef MRB_SG_SEGMENT_SIZE +#define MRB_SG_SEGMENT_SIZE 5 +#endif + +struct segkv { + mrb_value key; + mrb_value val; +}; + +typedef struct segment { + struct segment *next; + struct segkv e[MRB_SG_SEGMENT_SIZE]; +} segment; + +typedef struct segindex { + size_t size; + size_t capa; + struct segkv *table[]; +} segindex; + +/* Instance variable table structure */ +typedef struct seglist { + segment *rootseg; + segment *lastseg; + mrb_int size; + mrb_int last_len; + segindex *index; +} seglist; + +static /* inline */ size_t +sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key) { - enum mrb_vtype t = mrb_type(key); + enum mrb_vtype tt = mrb_type(key); mrb_value hv; - khint_t h; + size_t h; + segindex *index = t->index; + size_t capa = index ? index->capa : 0; - switch (t) { + switch (tt) { case MRB_TT_STRING: h = mrb_str_hash(mrb, key); break; @@ -35,23 +69,26 @@ mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #endif - h = (khint_t)mrb_obj_id(key); + h = (size_t)mrb_obj_id(key); break; default: hv = mrb_funcall(mrb, key, "hash", 0); - h = (khint_t)t ^ (khint_t)mrb_fixnum(hv); + h = (size_t)t ^ (size_t)mrb_fixnum(hv); break; } - return kh_int_hash_func(mrb, h); + if (index && (index != t->index || capa != index->capa)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); + } + return ((h)^((h)<<2)^((h)>>2)); } static inline mrb_bool -mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) +sg_hash_equal(mrb_state *mrb, seglist *t, mrb_value a, mrb_value b) { - enum mrb_vtype t = mrb_type(a); + enum mrb_vtype tt = mrb_type(a); - switch (t) { + switch (tt) { case MRB_TT_STRING: return mrb_str_equal(mrb, a, b); @@ -84,32 +121,18 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b) #endif default: - return mrb_eql(mrb, a, b); - } + { + segindex *index = t->index; + size_t capa = index ? index->capa : 0; + mrb_bool eql = mrb_eql(mrb, a, b); + if (index && (index != t->index || capa != index->capa)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); + } + return eql; + } + } } -/* return non zero to break the loop */ -typedef int (sg_foreach_func)(mrb_state *mrb,mrb_value key,mrb_value val, void *data); - -#ifndef MRB_SG_SEGMENT_SIZE -#define MRB_SG_SEGMENT_SIZE 5 -#endif - -typedef struct segment { - struct segment *next; - struct { - mrb_value key; - mrb_value val; - } e[MRB_SG_SEGMENT_SIZE]; -} segment; - -/* Instance variable table structure */ -typedef struct seglist { - segment *rootseg; - mrb_int size; - mrb_int last_len; -} seglist; - /* Creates the instance variable table. */ static seglist* sg_new(mrb_state *mrb) @@ -119,87 +142,87 @@ sg_new(mrb_state *mrb) t = (seglist*)mrb_malloc(mrb, sizeof(seglist)); t->size = 0; t->rootseg = NULL; + t->lastseg = NULL; t->last_len = 0; + t->index = NULL; return t; } -/* Set the value for the symbol in the instance variable table. */ +#define power2(v) do { \ + v--;\ + v |= v >> 1;\ + v |= v >> 2;\ + v |= v >> 4;\ + v |= v >> 8;\ + v |= v >> 16;\ + v++;\ +} while (0) + +#ifndef UPPER_BOUND +#define UPPER_BOUND(x) ((x)>>2|(x)>>1) +#endif + +#define SG_MASK(index) ((index->capa)-1) + +/* Build index for the segment list */ static void -sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) +sg_index(mrb_state *mrb, seglist *t) { + size_t size = (size_t)t->size; + size_t mask; + segindex *index = t->index; segment *seg; - segment *prev = NULL; - mrb_int i; + size_t i; - if (t == NULL) return; - seg = t->rootseg; - while (seg) { - for (i=0; ie[i].key; - /* Found room in last segment after last_len */ - if (!seg->next && i >= t->last_len) { - seg->e[i].key = key; - seg->e[i].val = val; - t->last_len = i+1; - if (t->size >= 0) t->size++; - return; - } - if (mrb_undef_p(k)) continue; - if (mrb_hash_ht_hash_equal(mrb, k, key)) { - seg->e[i].val = val; - return; - } + if (size < MRB_SG_SEGMENT_SIZE) { + if (index) { + failed: + mrb_free(mrb, index); + t->index = NULL; } - prev = seg; - seg = seg->next; + return; } - - /* Not found */ - if (t->size >= 0) t->size++; - - seg = (segment*)mrb_malloc(mrb, sizeof(segment)); - if (!seg) return; - seg->next = NULL; - seg->e[0].key = key; - seg->e[0].val = val; - t->last_len = 1; - if (prev) { - prev->next = seg; + /* allocate index table */ + if (index && index->size >= UPPER_BOUND(index->capa)) { + size = index->capa+1; } - else { - t->rootseg = seg; + power2(size); + if (!index || index->capa < size) { + index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size); + if (index == NULL) goto failed; + t->index = index; + } + index->size = t->size; + index->capa = size; + for (i=0; itable[i] = NULL; } -} - -/* Get a value for a symbol from the instance variable table. */ -static mrb_bool -sg_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) -{ - segment *seg; - mrb_int i; - if (t == NULL) return FALSE; + /* rebuld index */ + mask = SG_MASK(index); seg = t->rootseg; while (seg) { for (i=0; ie[i].key; + mrb_value key; + size_t k, step = 0; - if (!seg->next && i >= t->last_len) { - return FALSE; + if (!seg->next && i >= (size_t)t->last_len) { + return; } - if (mrb_undef_p(k)) continue; - if (mrb_hash_ht_hash_equal(mrb, k, key)) { - if (vp) *vp = seg->e[i].val; - return TRUE; + key = seg->e[i].key; + if (mrb_undef_p(key)) continue; + k = sg_hash_func(mrb, t, key) & mask; + while (index->table[k]) { + k = (k+(++step)) & mask; } + index->table[k] = &seg->e[i]; } seg = seg->next; } - return FALSE; } -/* Compacts the hash removing delete entries. */ +/* Compacts the segment list removing deleted entries. */ static void sg_compact(mrb_state *mrb, seglist *t) { @@ -209,6 +232,10 @@ sg_compact(mrb_state *mrb, seglist *t) mrb_int i2; mrb_int size = 0; + if (t->index && (size_t)t->size == t->index->size) { + sg_index(mrb, t); + return; + } while (seg) { for (i=0; ie[i].key; @@ -238,16 +265,179 @@ sg_compact(mrb_state *mrb, seglist *t) exit: /* reached at end */ t->size = size; - t->last_len = i2; - if (seg != seg2) { + if (seg2) { seg = seg2->next; seg2->next = NULL; + t->last_len = i2; + t->lastseg = seg2; while (seg) { seg2 = seg->next; mrb_free(mrb, seg); seg = seg2; } } + if (t->index) { + sg_index(mrb, t); + } +} + +/* Set the value for the key in the indexed segment list. */ +static void +sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) +{ + segindex *index = t->index; + size_t k, sp, step = 0, mask; + segment *seg; + + if (index->size >= UPPER_BOUND(index->capa)) { + /* need to expand table */ + sg_compact(mrb, t); + index = t->index; + } + mask = SG_MASK(index); + sp = index->capa; + k = sg_hash_func(mrb, t, key) & mask; + while (index->table[k]) { + mrb_value key2 = index->table[k]->key; + if (mrb_undef_p(key2)) { + if (sp == index->capa) sp = k; + } + else if (sg_hash_equal(mrb, t, key, key2)) { + index->table[k]->val = val; + return; + } + k = (k+(++step)) & mask; + } + if (sp < index->capa) { + k = sp; + } + + /* put the value at the last */ + seg = t->lastseg; + if (t->last_len < MRB_SG_SEGMENT_SIZE) { + index->table[k] = &seg->e[t->last_len++]; + } + else { /* append a new segment */ + seg->next = (segment*)mrb_malloc(mrb, sizeof(segment)); + seg = seg->next; + seg->next = NULL; + t->lastseg = seg; + t->last_len = 1; + index->table[k] = &seg->e[0]; + } + index->table[k]->key = key; + index->table[k]->val = val; + index->size++; + t->size++; +} + +/* Set the value for the key in the segment list. */ +static void +sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) +{ + segment *seg; + mrb_int i, deleted = 0; + + if (t == NULL) return; + if (t->index) { + sg_index_put(mrb, t, key, val); + return; + } + seg = t->rootseg; + while (seg) { + for (i=0; ie[i].key; + /* Found room in last segment after last_len */ + if (!seg->next && i >= t->last_len) { + seg->e[i].key = key; + seg->e[i].val = val; + t->last_len = i+1; + t->size++; + return; + } + if (mrb_undef_p(k)) { + deleted++; + continue; + } + if (sg_hash_equal(mrb, t, k, key)) { + seg->e[i].val = val; + return; + } + } + seg = seg->next; + } + + /* Not found */ + if (deleted > MRB_SG_SEGMENT_SIZE) { + sg_compact(mrb, t); + } + t->size++; + + seg = (segment*)mrb_malloc(mrb, sizeof(segment)); + seg->next = NULL; + seg->e[0].key = key; + seg->e[0].val = val; + t->last_len = 1; + if (t->rootseg == NULL) { + t->rootseg = seg; + } + else { + t->lastseg->next = seg; + } + t->lastseg = seg; + if (t->index == NULL && t->size > MRB_SG_SEGMENT_SIZE*4) { + sg_index(mrb, t); + } +} + +/* Get a value for a key from the indexed segment list. */ +static mrb_bool +sg_index_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) +{ + segindex *index = t->index; + size_t mask = SG_MASK(index); + size_t k = sg_hash_func(mrb, t, key) & mask; + size_t step = 0; + + while (index->table[k]) { + if (sg_hash_equal(mrb, t, key, index->table[k]->key)) { + if (vp) *vp = index->table[k]->val; + return TRUE; + } + k = (k+(++step)) & mask; + } + return FALSE; +} + +/* Get a value for a key from the segment list. */ +static mrb_bool +sg_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) +{ + segment *seg; + mrb_int i; + + if (t == NULL) return FALSE; + if (t->index) { + return sg_index_get(mrb, t, key, vp); + } + + seg = t->rootseg; + while (seg) { + for (i=0; ie[i].key; + + if (!seg->next && i >= t->last_len) { + return FALSE; + } + if (mrb_undef_p(k)) continue; + if (sg_hash_equal(mrb, t, k, key)) { + if (vp) *vp = seg->e[i].val; + return TRUE; + } + } + seg = seg->next; + } + return FALSE; } /* Deletes the value for the symbol from the instance variable table. */ @@ -262,18 +452,17 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) seg = t->rootseg; while (seg) { for (i=0; ie[i].key; + mrb_value key2; if (!seg->next && i >= t->last_len) { /* not found */ return FALSE; } - if (mrb_undef_p(k)) continue; - if (mrb_hash_ht_hash_equal(mrb, k, key)) { - if (vp) *vp = k; + key2 = seg->e[i].key; + if (!mrb_undef_p(key2) && sg_hash_equal(mrb, t, key, key2)) { + if (vp) *vp = key2; seg->e[i].key = mrb_undef_value(); - if (t->size > 0) t->size = -1; - else t->size--; /* count number of deleted */ + t->size--; return TRUE; } } @@ -290,6 +479,9 @@ sg_foreach(mrb_state *mrb, seglist *t, sg_foreach_func *func, void *p) mrb_int i; if (t == NULL) return; + if (t->index && t->index->size-(size_t)t->size > MRB_SG_SEGMENT_SIZE) { + sg_compact(mrb, t); + } seg = t->rootseg; while (seg) { for (i=0; isize < 0) { - sg_compact(mrb, t); - } return t->size; } @@ -355,13 +544,14 @@ sg_free(mrb_state *mrb, seglist *t) seg = seg->next; mrb_free(mrb, p); } + if (t->index) mrb_free(mrb, t->index); mrb_free(mrb, t); } static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value -mrb_hash_ht_key(mrb_state *mrb, mrb_value key) +ht_key(mrb_state *mrb, mrb_value key) { if (mrb_string_p(key) && !MRB_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); @@ -370,7 +560,7 @@ mrb_hash_ht_key(mrb_state *mrb, mrb_value key) return key; } -#define KEY(key) mrb_hash_ht_key(mrb, key) +#define KEY(key) ht_key(mrb, key) static int hash_mark_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p) @@ -489,15 +679,6 @@ mrb_hash_dup(mrb_state *mrb, mrb_value self) return mrb_obj_value(copy); } -MRB_API mrb_bool -mrb_hash_has_key_p(mrb_state *mrb, mrb_value hash, mrb_value key) -{ - if (sg_get(mrb, RHASH_TBL(hash), key, NULL)) { - return TRUE; - } - return FALSE; -} - MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { @@ -821,6 +1002,33 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self) return mrb_hash_delete_key(mrb, self, key); } +/* find first element in segment list, and remove it. */ +static void +sg_shift(mrb_state *mrb, seglist *t, mrb_value *kp, mrb_value *vp) +{ + segment *seg = t->rootseg; + mrb_int i; + + while (seg) { + for (i=0; inext && i >= t->last_len) { + return; + } + key = seg->e[i].key; + if (mrb_undef_p(key)) continue; + *kp = key; + *vp = seg->e[i].val; + /* delete element */ + seg->e[i].key = mrb_undef_value(); + t->size--; + return; + } + seg = seg->next; + } +} + /* 15.2.13.4.24 */ /* * call-seq: @@ -842,9 +1050,9 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) mrb_hash_modify(mrb, hash); if (sg && sg_size(mrb, sg) > 0) { - mrb_value del_key = sg->rootseg->e[0].key; - mrb_value del_val = sg->rootseg->e[0].val; - sg_del(mrb, sg, del_key, NULL); + mrb_value del_key, del_val; + + sg_shift(mrb, sg, &del_key, &del_val); return mrb_assoc_new(mrb, del_key, del_val); } -- cgit v1.2.3 From ab0f4db688248a27faba904a0b2bdc55ba9e5ac9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 12 Oct 2018 19:00:14 +0900 Subject: Call `uniq!` for each union processing in `Array#union`. --- mrbgems/mruby-array-ext/mrblib/array.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index eac8d4718..ed3f591fe 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -143,11 +143,11 @@ class Array # def union(*args) ary = self.dup - args.each_with_index do |x,i| + args.each do |x| ary.concat(x) - ary.uniq! if i % 20 == 0 + ary.uniq! end - ary.uniq! or ary + ary end ## -- cgit v1.2.3 From 426c1f9e0b77a27d5384ccdee7f7a49eef0e2ed0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 19 Nov 2018 11:28:03 +0900 Subject: fix non-ASCII comment. --- mrbgems/mruby-array-ext/mrblib/array.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index ed3f591fe..42da0207e 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -1,4 +1,3 @@ -# coding: cp932 class Array ## # call-seq: @@ -927,7 +926,7 @@ class Array # # Assumes that self is an array of arrays and transposes the rows and columns. # - # If the length of the subarrays don’t match, an IndexError is raised. + # If the length of the subarrays don't match, an IndexError is raised. # # Examples: # -- cgit v1.2.3 From 5bbcea9b3bdb0e7dc048f92cebefb54858196935 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 22:01:28 +0900 Subject: Removed `try_convert` method from Array and Hash. --- mrbgems/mruby-array-ext/mrblib/array.rb | 25 ------------------------- mrbgems/mruby-array-ext/test/array.rb | 7 ------- mrbgems/mruby-hash-ext/mrblib/hash.rb | 19 ------------------- mrbgems/mruby-hash-ext/test/hash.rb | 6 ------ 4 files changed, 57 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 42da0207e..54d62e3fd 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -1,29 +1,4 @@ class Array - ## - # call-seq: - # Array.try_convert(obj) -> array or nil - # - # Tries to convert +obj+ into an array, using +to_ary+ method. - # converted array or +nil+ if +obj+ cannot be converted for any reason. - # This method can be used to check if an argument is an array. - # - # Array.try_convert([1]) #=> [1] - # Array.try_convert("1") #=> nil - # - # if tmp = Array.try_convert(arg) - # # the argument is an array - # elsif tmp = String.try_convert(arg) - # # the argument is a string - # end - # - def self.try_convert(obj) - if obj.respond_to?(:to_ary) - obj.to_ary - else - nil - end - end - ## # call-seq: # ary.uniq! -> ary or nil diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 84f9cfeaf..b7467724c 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -1,13 +1,6 @@ ## # Array(Ext) Test -assert("Array.try_convert") do - assert_nil Array.try_convert(0) - assert_nil Array.try_convert(nil) - assert_equal [], Array.try_convert([]) - assert_equal [1,2,3], Array.try_convert([1,2,3]) -end - assert("Array#assoc") do s1 = [ "colors", "red", "blue", "green" ] s2 = [ "letters", "a", "b", "c" ] diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index 5bbbdf559..f1143e25b 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -60,25 +60,6 @@ class Hash h end - ## - # call-seq: - # Hash.try_convert(obj) -> hash or nil - # - # Try to convert obj into a hash, using to_hash method. - # Returns converted hash or nil if obj cannot be converted - # for any reason. - # - # Hash.try_convert({1=>2}) # => {1=>2} - # Hash.try_convert("1=>2") # => nil - # - def self.try_convert(obj) - if obj.respond_to?(:to_hash) - obj.to_hash - else - nil - end - end - ## # call-seq: # hsh.merge!(other_hash) -> hsh diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb index 269da800d..b5d0aaaf8 100644 --- a/mrbgems/mruby-hash-ext/test/hash.rb +++ b/mrbgems/mruby-hash-ext/test/hash.rb @@ -45,12 +45,6 @@ assert('Hash.[] for sub class') do assert_equal(sub_hash_class, sub_hash.class) end -assert('Hash.try_convert') do - assert_nil Hash.try_convert(nil) - assert_nil Hash.try_convert("{1=>2}") - assert_equal({1=>2}, Hash.try_convert({1=>2})) -end - assert('Hash#merge!') do a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } -- cgit v1.2.3 From 698f5f707c2db334a15c605bf1b0d0cff42b1224 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 22:19:55 +0900 Subject: Removed `to_ary` conversion method. --- include/mruby/array.h | 1 + mrbgems/mruby-array-ext/mrblib/array.rb | 10 ---------- mrbgems/mruby-array-ext/test/array.rb | 16 ---------------- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 4 +--- mrbgems/mruby-kernel-ext/src/kernel.c | 9 ++------- src/array.c | 27 +++++---------------------- src/class.c | 3 ++- src/object.c | 17 +++++++++++++++++ 8 files changed, 28 insertions(+), 59 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/include/mruby/array.h b/include/mruby/array.h index 6fffe4512..2457f68f2 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -199,6 +199,7 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val * @param other The array to replace it with. */ MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); +MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); /* diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 54d62e3fd..bb95d70c5 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -772,16 +772,6 @@ class Array nil end - ## - # call-seq: - # ary.to_ary -> ary - # - # Returns +self+. - # - def to_ary - self - end - ## # call-seq: # ary.dig(idx, ...) -> object diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index b7467724c..853554bcc 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -331,27 +331,11 @@ assert('Array#to_h') do assert_raise(ArgumentError) { [[1]].to_h } end -assert('Array#to_h (Modified)') do - class A - def to_ary - $a.clear - nil - end - end - $a = [A.new] - assert_raise(TypeError) { $a.to_h } -end - assert("Array#index (block)") do assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } end -assert("Array#to_ary") do - assert_equal [], [].to_ary - assert_equal [1,2,3], [1,2,3].to_ary -end - assert("Array#dig") do h = [[[1]], 0] assert_equal(1, h.dig(0, 0, 0)) diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 6dd971f3a..9d80bc552 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -624,9 +624,7 @@ module Enumerable # use Enumerator to use infinite sequence def zip(*args, &block) args = args.map do |a| - if a.respond_to?(:to_ary) - a.to_ary.to_enum(:each) - elsif a.respond_to?(:each) + if a.respond_to?(:each) a.to_enum(:each) else raise TypeError, "wrong argument type #{a.class} (must respond to :each)" diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index bc2656399..324753f6e 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -161,9 +161,7 @@ mrb_f_string(mrb_state *mrb, mrb_value self) * call-seq: * Array(arg) -> array * - * Returns +arg+ as an Array. - * - * First tries to call Array#to_ary on +arg+, then Array#to_a. + * Returns +arg+ as an Array using to_a method. * * Array(1..5) #=> [1, 2, 3, 4, 5] * @@ -174,10 +172,7 @@ mrb_f_array(mrb_state *mrb, mrb_value self) mrb_value arg, tmp; mrb_get_args(mrb, "o", &arg); - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_ary"); - if (mrb_nil_p(tmp)) { - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a"); - } + tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a"); if (mrb_nil_p(tmp)) { return mrb_ary_new_from_values(mrb, 1, &arg); } diff --git a/src/array.c b/src/array.c index eddd9b2ac..084b48dc0 100644 --- a/src/array.c +++ b/src/array.c @@ -1058,7 +1058,7 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value v) { - mrb_value a, recv_class; + mrb_value a; if (mrb_array_p(v)) { return v; @@ -1069,22 +1069,11 @@ mrb_ary_splat(mrb_state *mrb, mrb_value v) } a = mrb_funcall(mrb, v, "to_a", 0); - if (mrb_array_p(a)) { - return a; - } - else if (mrb_nil_p(a)) { + if (mrb_nil_p(a)) { return mrb_ary_new_from_values(mrb, 1, &v); } - else { - recv_class = mrb_obj_value(mrb_obj_class(mrb, v)); - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)", - recv_class, - recv_class, - mrb_obj_value(mrb_obj_class(mrb, a)) - ); - /* not reached */ - return mrb_undef_value(); - } + mrb_ensure_array_type(mrb, a); + return a; } static mrb_value @@ -1122,12 +1111,6 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self) return mrb_bool_value(ARY_LEN(a) == 0); } -MRB_API mrb_value -mrb_check_array_type(mrb_state *mrb, mrb_value ary) -{ - return mrb_check_convert_type(mrb, ary, MRB_TT_ARRAY, "Array", "to_ary"); -} - MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset) { @@ -1181,7 +1164,7 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) val = tmp; goto str_join; } - tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); + tmp = mrb_check_array_type(mrb, val); if (!mrb_nil_p(tmp)) { val = tmp; goto ary_join; diff --git a/src/class.c b/src/class.c index 90c73104e..5d6ff4b39 100644 --- a/src/class.c +++ b/src/class.c @@ -520,7 +520,8 @@ to_str(mrb_state *mrb, mrb_value val) static mrb_value to_ary(mrb_state *mrb, mrb_value val) { - return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); + CHECK_TYPE(mrb, val, MRB_TT_ARRAY, "Array"); + return val; } static mrb_value diff --git a/src/object.c b/src/object.c index 18ccacfb9..a105c62f0 100644 --- a/src/object.c +++ b/src/object.c @@ -606,6 +606,23 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str) return str; } +MRB_API mrb_value +mrb_ensure_array_type(mrb_state *mrb, mrb_value ary) +{ + if (!mrb_array_p(ary)) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to Array", + inspect_type(mrb, ary)); + } + return ary; +} + +MRB_API mrb_value +mrb_check_array_type(mrb_state *mrb, mrb_value ary) +{ + if (!mrb_array_p(ary)) return mrb_nil_value(); + return ary; +} + MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj) { -- cgit v1.2.3 From 7ed9bb3bd361030c3fbeeaf72186e61c8e6563f0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 25 Nov 2018 06:03:30 +0900 Subject: Fix wrong number of arguments in `Array#fetch`; fix #4170 --- mrbgems/mruby-array-ext/mrblib/array.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index bb95d70c5..6096696cb 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -291,7 +291,7 @@ class Array # #=> "100 is out of bounds" # - def fetch(n=nil, ifnone=NONE, &block) + def fetch(n, ifnone=NONE, &block) warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block idx = n -- cgit v1.2.3 From 6da3cd5d2296b9cd205772851f0a30e3af730c70 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Fri, 1 Feb 2019 16:02:01 +0900 Subject: Move `NONE` to `mrblib/enum.rb` --- mrbgems/mruby-array-ext/mrblib/array.rb | 1 - mrbgems/mruby-enum-ext/mrblib/enum.rb | 1 - mrblib/enum.rb | 2 ++ 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 6096696cb..387bd6c90 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -266,7 +266,6 @@ class Array self end - NONE=Object.new ## # call-seq: # ary.fetch(index) -> obj diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index fedf8b1ae..99b9cddba 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -205,7 +205,6 @@ module Enumerable ary.collect{|e,i| orig[i]} end - NONE = Object.new ## # call-seq: # enum.first -> obj or nil diff --git a/mrblib/enum.rb b/mrblib/enum.rb index a97a26f97..9bd74e1c4 100644 --- a/mrblib/enum.rb +++ b/mrblib/enum.rb @@ -13,6 +13,8 @@ # @ISO 15.3.2 module Enumerable + NONE = Object.new + ## # Call the given block for each element # which is yield by +each+. Return false -- cgit v1.2.3 From 5adef8ba44b92ca01692451e21af5c3f47e8853c Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sat, 6 Apr 2019 17:40:51 +0900 Subject: Move `Array#(append|prepend)` from core to `mruby-ary-ext` They are not included in ISO standard. --- mrbgems/mruby-array-ext/mrblib/array.rb | 3 +++ src/array.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-array-ext/mrblib/array.rb') diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index 387bd6c90..59b6087d2 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -936,4 +936,7 @@ class Array end h end + + alias append push + alias prepend unshift end diff --git a/src/array.c b/src/array.c index 707820ab9..43f4c98b5 100644 --- a/src/array.c +++ b/src/array.c @@ -1286,7 +1286,6 @@ mrb_init_array(mrb_state *mrb) mrb_define_method(mrb, a, "length", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */ mrb_define_method(mrb, a, "pop", mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */ mrb_define_method(mrb, a, "push", mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */ - mrb_define_method(mrb, a, "append", mrb_ary_push_m, MRB_ARGS_ANY()); mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */ mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */ mrb_define_method(mrb, a, "reverse!", mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */ @@ -1295,7 +1294,6 @@ mrb_init_array(mrb_state *mrb) mrb_define_method(mrb, a, "size", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */ mrb_define_method(mrb, a, "slice", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.29 */ mrb_define_method(mrb, a, "unshift", mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */ - mrb_define_method(mrb, a, "prepend", mrb_ary_unshift_m, MRB_ARGS_ANY()); mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1)); mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1)); -- cgit v1.2.3