1 /**********************************************************************
6 created at: Fri Aug 6 09:46:12 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "debug_counter.h"
17 #include "internal/array.h"
18 #include "internal/compar.h"
19 #include "internal/enum.h"
20 #include "internal/gc.h"
21 #include "internal/hash.h"
22 #include "internal/numeric.h"
23 #include "internal/object.h"
24 #include "internal/proc.h"
25 #include "internal/rational.h"
26 #include "internal/vm.h"
28 #include "ruby/encoding.h"
30 #include "ruby/thread.h"
31 #include "ruby/util.h"
39 #include "ruby_assert.h"
42 VALUE rb_cArray_empty_frozen
;
46 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
47 * The array is shared. The buffer this array points to is owned by
48 * another array (the shared root).
49 * 1: RARRAY_EMBED_FLAG
50 * The array is embedded (its contents follow the header, rather than
51 * being on a separately allocated buffer).
52 * 3-9: RARRAY_EMBED_LEN
53 * The length of the array when RARRAY_EMBED_FLAG is set.
54 * 12: RARRAY_SHARED_ROOT_FLAG
55 * The array is a shared root that does reference counting. The buffer
56 * this array points to is owned by this array but may be pointed to
58 * Note: Frozen arrays may be a shared root without this flag being
59 * set. Frozen arrays do not have reference counting because
60 * they cannot be modified. Not updating the reference count
61 * improves copy-on-write performance. Their reference count is
62 * assumed to be infinity.
63 * 14: RARRAY_PTR_IN_USE_FLAG
64 * The buffer of the array is in use. This is only used during
68 /* for OPTIMIZED_CMP: */
71 #define ARY_DEFAULT_SIZE 16
72 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
73 #define SMALL_ARRAY_LEN 16
75 RBIMPL_ATTR_MAYBE_UNUSED()
77 should_be_T_ARRAY(VALUE ary
)
79 return RB_TYPE_P(ary
, T_ARRAY
);
82 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
83 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
84 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
85 RARRAY(a)->as.heap.aux.capa)
87 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
88 #define ARY_EMBED_LEN(a) \
89 (RUBY_ASSERT(ARY_EMBED_P(a)), \
90 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
91 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
92 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
94 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
95 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
97 #define FL_SET_EMBED(a) do { \
98 RUBY_ASSERT(!ARY_SHARED_P(a)); \
99 FL_SET((a), RARRAY_EMBED_FLAG); \
103 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
104 #define FL_SET_SHARED(ary) do { \
105 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
106 FL_SET((ary), RARRAY_SHARED_FLAG); \
108 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
110 #define ARY_SET_PTR(ary, p) do { \
111 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
112 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
113 RARRAY(ary)->as.heap.ptr = (p); \
115 #define ARY_SET_EMBED_LEN(ary, n) do { \
117 RUBY_ASSERT(ARY_EMBED_P(ary)); \
118 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
119 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
121 #define ARY_SET_HEAP_LEN(ary, n) do { \
122 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
123 RARRAY(ary)->as.heap.len = (n); \
125 #define ARY_SET_LEN(ary, n) do { \
126 if (ARY_EMBED_P(ary)) { \
127 ARY_SET_EMBED_LEN((ary), (n)); \
130 ARY_SET_HEAP_LEN((ary), (n)); \
132 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
134 #define ARY_INCREASE_PTR(ary, n) do { \
135 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
136 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
137 RARRAY(ary)->as.heap.ptr += (n); \
139 #define ARY_INCREASE_LEN(ary, n) do { \
140 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
141 if (ARY_EMBED_P(ary)) { \
142 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
145 RARRAY(ary)->as.heap.len += (n); \
149 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
150 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
151 #define ARY_SET_CAPA(ary, n) do { \
152 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
153 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
154 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
155 RARRAY(ary)->as.heap.aux.capa = (n); \
158 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
159 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
160 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
161 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
162 RUBY_ASSERT((value) >= 0); \
163 RARRAY(ary)->as.heap.aux.capa = (value); \
165 #define FL_SET_SHARED_ROOT(ary) do { \
166 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
167 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
168 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
172 ARY_SET(VALUE a
, long i
, VALUE v
)
174 RUBY_ASSERT(!ARY_SHARED_P(a
));
175 RUBY_ASSERT(!OBJ_FROZEN(a
));
177 RARRAY_ASET(a
, i
, v
);
182 ary_embed_capa(VALUE ary
)
184 size_t size
= rb_gc_obj_slot_size(ary
) - offsetof(struct RArray
, as
.ary
);
185 RUBY_ASSERT(size
% sizeof(VALUE
) == 0);
186 return size
/ sizeof(VALUE
);
190 ary_embed_size(long capa
)
192 return offsetof(struct RArray
, as
.ary
) + (sizeof(VALUE
) * capa
);
196 ary_embeddable_p(long capa
)
198 return rb_gc_size_allocatable_p(ary_embed_size(capa
));
202 rb_ary_embeddable_p(VALUE ary
)
204 /* An array cannot be turned embeddable when the array is:
205 * - Shared root: other objects may point to the buffer of this array
206 * so we cannot make it embedded.
207 * - Frozen: this array may also be a shared root without the shared root
209 * - Shared: we don't want to re-embed an array that points to a shared
210 * root (to save memory).
212 return !(ARY_SHARED_ROOT_P(ary
) || OBJ_FROZEN(ary
) || ARY_SHARED_P(ary
));
216 rb_ary_size_as_embedded(VALUE ary
)
220 if (ARY_EMBED_P(ary
)) {
221 real_size
= ary_embed_size(ARY_EMBED_LEN(ary
));
223 else if (rb_ary_embeddable_p(ary
)) {
224 real_size
= ary_embed_size(ARY_HEAP_CAPA(ary
));
227 real_size
= sizeof(struct RArray
);
234 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
237 ary_verify_(VALUE ary
, const char *file
, int line
)
239 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
241 if (ARY_SHARED_P(ary
)) {
242 VALUE root
= ARY_SHARED_ROOT(ary
);
243 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
244 const VALUE
*root_ptr
= RARRAY_CONST_PTR(root
);
245 long len
= ARY_HEAP_LEN(ary
), root_len
= RARRAY_LEN(root
);
246 RUBY_ASSERT(ARY_SHARED_ROOT_P(root
) || OBJ_FROZEN(root
));
247 RUBY_ASSERT(root_ptr
<= ptr
&& ptr
+ len
<= root_ptr
+ root_len
);
250 else if (ARY_EMBED_P(ary
)) {
251 RUBY_ASSERT(!ARY_SHARED_P(ary
));
252 RUBY_ASSERT(RARRAY_LEN(ary
) <= ary_embed_capa(ary
));
255 const VALUE
*ptr
= RARRAY_CONST_PTR(ary
);
256 long i
, len
= RARRAY_LEN(ary
);
258 if (len
> 1) len
= 1; /* check only HEAD */
259 for (i
=0; i
<len
; i
++) {
260 v
= ptr
[i
]; /* access check */
268 #define ary_verify(ary) ((void)0)
272 rb_ary_ptr_use_start(VALUE ary
)
275 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
277 return (VALUE
*)RARRAY_CONST_PTR(ary
);
281 rb_ary_ptr_use_end(VALUE ary
)
284 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
289 rb_mem_clear(VALUE
*mem
, long size
)
297 ary_mem_clear(VALUE ary
, long beg
, long size
)
299 RARRAY_PTR_USE(ary
, ptr
, {
300 rb_mem_clear(ptr
+ beg
, size
);
305 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
313 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
315 RARRAY_PTR_USE(ary
, ptr
, {
316 memfill(ptr
+ beg
, size
, val
);
317 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
322 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
324 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary
));
326 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
327 rb_gc_writebarrier_remember(buff_owner_ary
);
328 RARRAY_PTR_USE(ary
, ptr
, {
329 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
334 RARRAY_PTR_USE(ary
, ptr
, {
335 for (i
=0; i
<argc
; i
++) {
336 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
343 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
345 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
349 ary_heap_alloc_buffer(size_t capa
)
351 return ALLOC_N(VALUE
, capa
);
355 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
357 ruby_sized_xfree((void *)ptr
, size
);
361 ary_heap_free(VALUE ary
)
363 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
367 ary_heap_realloc(VALUE ary
, size_t new_capa
)
369 RUBY_ASSERT(!OBJ_FROZEN(ary
));
370 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, ARY_HEAP_CAPA(ary
));
377 rb_ary_make_embedded(VALUE ary
)
379 RUBY_ASSERT(rb_ary_embeddable_p(ary
));
380 if (!ARY_EMBED_P(ary
)) {
381 const VALUE
*buf
= ARY_HEAP_PTR(ary
);
382 long len
= ARY_HEAP_LEN(ary
);
385 ARY_SET_EMBED_LEN(ary
, len
);
387 MEMCPY((void *)ARY_EMBED_PTR(ary
), (void *)buf
, VALUE
, len
);
389 ary_heap_free_ptr(ary
, buf
, len
* sizeof(VALUE
));
394 ary_resize_capa(VALUE ary
, long capacity
)
396 RUBY_ASSERT(RARRAY_LEN(ary
) <= capacity
);
397 RUBY_ASSERT(!OBJ_FROZEN(ary
));
398 RUBY_ASSERT(!ARY_SHARED_P(ary
));
400 if (capacity
> ary_embed_capa(ary
)) {
401 size_t new_capa
= capacity
;
402 if (ARY_EMBED_P(ary
)) {
403 long len
= ARY_EMBED_LEN(ary
);
404 VALUE
*ptr
= ary_heap_alloc_buffer(capacity
);
406 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
408 ARY_SET_PTR(ary
, ptr
);
409 ARY_SET_HEAP_LEN(ary
, len
);
412 new_capa
= ary_heap_realloc(ary
, capacity
);
414 ARY_SET_CAPA(ary
, new_capa
);
417 if (!ARY_EMBED_P(ary
)) {
418 long len
= ARY_HEAP_LEN(ary
);
419 long old_capa
= ARY_HEAP_CAPA(ary
);
420 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
422 if (len
> capacity
) len
= capacity
;
423 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
424 ary_heap_free_ptr(ary
, ptr
, old_capa
);
427 ARY_SET_LEN(ary
, len
);
435 ary_shrink_capa(VALUE ary
)
437 long capacity
= ARY_HEAP_LEN(ary
);
438 long old_capa
= ARY_HEAP_CAPA(ary
);
439 RUBY_ASSERT(!ARY_SHARED_P(ary
));
440 RUBY_ASSERT(old_capa
>= capacity
);
441 if (old_capa
> capacity
) {
442 size_t new_capa
= ary_heap_realloc(ary
, capacity
);
443 ARY_SET_CAPA(ary
, new_capa
);
450 ary_double_capa(VALUE ary
, long min
)
452 long new_capa
= ARY_CAPA(ary
) / 2;
454 if (new_capa
< ARY_DEFAULT_SIZE
) {
455 new_capa
= ARY_DEFAULT_SIZE
;
457 if (new_capa
>= ARY_MAX_SIZE
- min
) {
458 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
461 ary_resize_capa(ary
, new_capa
);
467 rb_ary_decrement_share(VALUE shared_root
)
469 if (!OBJ_FROZEN(shared_root
)) {
470 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
471 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
- 1);
476 rb_ary_unshare(VALUE ary
)
478 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
479 rb_ary_decrement_share(shared_root
);
480 FL_UNSET_SHARED(ary
);
484 rb_ary_reset(VALUE ary
)
486 if (ARY_OWNS_HEAP_P(ary
)) {
489 else if (ARY_SHARED_P(ary
)) {
494 ARY_SET_EMBED_LEN(ary
, 0);
498 rb_ary_increment_share(VALUE shared_root
)
500 if (!OBJ_FROZEN(shared_root
)) {
501 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
502 RUBY_ASSERT(num
>= 0);
503 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
509 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
511 RUBY_ASSERT(!ARY_EMBED_P(ary
));
512 RUBY_ASSERT(!OBJ_FROZEN(ary
));
513 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root
) || OBJ_FROZEN(shared_root
));
515 rb_ary_increment_share(shared_root
);
517 RB_OBJ_WRITE(ary
, &RARRAY(ary
)->as
.heap
.aux
.shared_root
, shared_root
);
519 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
523 rb_ary_modify_check(VALUE ary
)
525 RUBY_ASSERT(ruby_thread_has_gvl_p());
527 rb_check_frozen(ary
);
532 rb_ary_cancel_sharing(VALUE ary
)
534 if (ARY_SHARED_P(ary
)) {
535 long shared_len
, len
= RARRAY_LEN(ary
);
536 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
538 ary_verify(shared_root
);
540 if (len
<= ary_embed_capa(ary
)) {
541 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
542 FL_UNSET_SHARED(ary
);
544 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
545 rb_ary_decrement_share(shared_root
);
546 ARY_SET_EMBED_LEN(ary
, len
);
548 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
549 long shift
= RARRAY_CONST_PTR(ary
) - RARRAY_CONST_PTR(shared_root
);
550 FL_UNSET_SHARED(ary
);
551 ARY_SET_PTR(ary
, RARRAY_CONST_PTR(shared_root
));
552 ARY_SET_CAPA(ary
, shared_len
);
553 RARRAY_PTR_USE(ary
, ptr
, {
554 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
556 FL_SET_EMBED(shared_root
);
557 rb_ary_decrement_share(shared_root
);
560 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
561 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
563 ARY_SET_CAPA(ary
, len
);
564 ARY_SET_PTR(ary
, ptr
);
567 rb_gc_writebarrier_remember(ary
);
573 rb_ary_modify(VALUE ary
)
575 rb_ary_modify_check(ary
);
576 rb_ary_cancel_sharing(ary
);
580 ary_ensure_room_for_push(VALUE ary
, long add_len
)
582 long old_len
= RARRAY_LEN(ary
);
583 long new_len
= old_len
+ add_len
;
586 if (old_len
> ARY_MAX_SIZE
- add_len
) {
587 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
589 if (ARY_SHARED_P(ary
)) {
590 if (new_len
> ary_embed_capa(ary
)) {
591 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
592 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
593 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
594 rb_ary_modify_check(ary
);
597 ary_verify(shared_root
);
601 /* if array is shared, then it is likely it participate in push/shift pattern */
603 capa
= ARY_CAPA(ary
);
604 if (new_len
> capa
- (capa
>> 6)) {
605 ary_double_capa(ary
, new_len
);
616 rb_ary_modify_check(ary
);
618 capa
= ARY_CAPA(ary
);
619 if (new_len
> capa
) {
620 ary_double_capa(ary
, new_len
);
631 * Freezes +self+ (if not already frozen); returns +self+:
634 * a.frozen? # => false
636 * a.frozen? # => true
638 * No further changes may be made to +self+;
639 * raises FrozenError if a change is attempted.
641 * Related: Kernel#frozen?.
645 rb_ary_freeze(VALUE ary
)
647 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
649 if (OBJ_FROZEN(ary
)) return ary
;
651 if (!ARY_EMBED_P(ary
) && !ARY_SHARED_P(ary
) && !ARY_SHARED_ROOT_P(ary
)) {
652 ary_shrink_capa(ary
);
655 return rb_obj_freeze(ary
);
658 /* This can be used to take a snapshot of an array (with
659 e.g. rb_ary_replace) and check later whether the array has been
660 modified from the snapshot. The snapshot is cheap, though if
661 something does modify the array it will pay the cost of copying
662 it. If Array#pop or Array#shift has been called, the array will
663 be still shared with the snapshot, but the array length will
666 rb_ary_shared_with_p(VALUE ary1
, VALUE ary2
)
668 if (!ARY_EMBED_P(ary1
) && ARY_SHARED_P(ary1
) &&
669 !ARY_EMBED_P(ary2
) && ARY_SHARED_P(ary2
) &&
670 ARY_SHARED_ROOT(ary1
) == ARY_SHARED_ROOT(ary2
) &&
671 ARY_HEAP_LEN(ary1
) == ARY_HEAP_LEN(ary2
)) {
678 ary_alloc_embed(VALUE klass
, long capa
)
680 size_t size
= ary_embed_size(capa
);
681 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
682 NEWOBJ_OF(ary
, struct RArray
, klass
,
683 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
686 * FL_SET_EMBED((VALUE)ary);
687 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
693 ary_alloc_heap(VALUE klass
)
695 NEWOBJ_OF(ary
, struct RArray
, klass
,
696 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
697 sizeof(struct RArray
), 0);
702 empty_ary_alloc(VALUE klass
)
704 RUBY_DTRACE_CREATE_HOOK(ARRAY
, 0);
705 return ary_alloc_embed(klass
, 0);
709 ary_new(VALUE klass
, long capa
)
711 RUBY_ASSERT(ruby_thread_has_gvl_p());
716 rb_raise(rb_eArgError
, "negative array size (or size too big)");
718 if (capa
> ARY_MAX_SIZE
) {
719 rb_raise(rb_eArgError
, "array size too big");
722 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
724 if (ary_embeddable_p(capa
)) {
725 ary
= ary_alloc_embed(klass
, capa
);
728 ary
= ary_alloc_heap(klass
);
729 ARY_SET_CAPA(ary
, capa
);
730 RUBY_ASSERT(!ARY_EMBED_P(ary
));
732 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
733 ARY_SET_HEAP_LEN(ary
, 0);
740 rb_ary_new_capa(long capa
)
742 return ary_new(rb_cArray
, capa
);
748 return rb_ary_new_capa(0);
752 (rb_ary_new_from_args
)(long n
, ...)
758 ary
= rb_ary_new2(n
);
761 for (i
=0; i
<n
; i
++) {
762 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
771 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
775 ary
= ary_new(klass
, n
);
777 ary_memcpy(ary
, 0, n
, elts
);
785 rb_ary_new_from_values(long n
, const VALUE
*elts
)
787 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
791 ec_ary_alloc_embed(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
793 size_t size
= ary_embed_size(capa
);
794 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
795 NEWOBJ_OF(ary
, struct RArray
, klass
,
796 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
799 * FL_SET_EMBED((VALUE)ary);
800 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
806 ec_ary_alloc_heap(rb_execution_context_t
*ec
, VALUE klass
)
808 NEWOBJ_OF(ary
, struct RArray
, klass
,
809 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
810 sizeof(struct RArray
), ec
);
815 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
820 rb_raise(rb_eArgError
, "negative array size (or size too big)");
822 if (capa
> ARY_MAX_SIZE
) {
823 rb_raise(rb_eArgError
, "array size too big");
826 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
828 if (ary_embeddable_p(capa
)) {
829 ary
= ec_ary_alloc_embed(ec
, klass
, capa
);
832 ary
= ec_ary_alloc_heap(ec
, klass
);
833 ARY_SET_CAPA(ary
, capa
);
834 RUBY_ASSERT(!ARY_EMBED_P(ary
));
836 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
837 ARY_SET_HEAP_LEN(ary
, 0);
844 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
848 ary
= ec_ary_new(ec
, rb_cArray
, n
);
850 ary_memcpy(ary
, 0, n
, elts
);
858 rb_ary_hidden_new(long capa
)
860 VALUE ary
= ary_new(0, capa
);
865 rb_ary_hidden_new_fill(long capa
)
867 VALUE ary
= rb_ary_hidden_new(capa
);
868 ary_memfill(ary
, 0, capa
, Qnil
);
869 ARY_SET_LEN(ary
, capa
);
874 rb_ary_free(VALUE ary
)
876 if (ARY_OWNS_HEAP_P(ary
)) {
877 if (USE_DEBUG_COUNTER
&&
878 !ARY_SHARED_ROOT_P(ary
) &&
879 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
880 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
883 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
887 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
890 if (ARY_SHARED_P(ary
)) {
891 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
893 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
894 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
898 static VALUE fake_ary_flags
;
901 init_fake_ary_flags(void)
903 struct RArray fake_ary
= {0};
904 fake_ary
.basic
.flags
= T_ARRAY
;
905 VALUE ary
= (VALUE
)&fake_ary
;
907 return fake_ary
.basic
.flags
;
911 rb_setup_fake_ary(struct RArray
*fake_ary
, const VALUE
*list
, long len
)
913 fake_ary
->basic
.flags
= fake_ary_flags
;
914 RBASIC_CLEAR_CLASS((VALUE
)fake_ary
);
916 // bypass frozen checks
917 fake_ary
->as
.heap
.ptr
= list
;
918 fake_ary
->as
.heap
.len
= len
;
919 fake_ary
->as
.heap
.aux
.capa
= len
;
920 return (VALUE
)fake_ary
;
924 rb_ary_memsize(VALUE ary
)
926 if (ARY_OWNS_HEAP_P(ary
)) {
927 return ARY_CAPA(ary
) * sizeof(VALUE
);
935 ary_make_shared(VALUE ary
)
939 if (ARY_SHARED_P(ary
)) {
940 return ARY_SHARED_ROOT(ary
);
942 else if (ARY_SHARED_ROOT_P(ary
)) {
945 else if (OBJ_FROZEN(ary
)) {
949 long capa
= ARY_CAPA(ary
);
950 long len
= RARRAY_LEN(ary
);
952 /* Shared roots cannot be embedded because the reference count
953 * (refcnt) is stored in as.heap.aux.capa. */
954 VALUE shared
= ary_alloc_heap(0);
955 FL_SET_SHARED_ROOT(shared
);
957 if (ARY_EMBED_P(ary
)) {
958 VALUE
*ptr
= ary_heap_alloc_buffer(capa
);
959 ARY_SET_PTR(shared
, ptr
);
960 ary_memcpy(shared
, 0, len
, RARRAY_CONST_PTR(ary
));
963 ARY_SET_HEAP_LEN(ary
, len
);
964 ARY_SET_PTR(ary
, ptr
);
967 ARY_SET_PTR(shared
, RARRAY_CONST_PTR(ary
));
970 ARY_SET_LEN(shared
, capa
);
971 ary_mem_clear(shared
, len
, capa
- len
);
972 rb_ary_set_shared(ary
, shared
);
982 ary_make_substitution(VALUE ary
)
984 long len
= RARRAY_LEN(ary
);
986 if (ary_embeddable_p(len
)) {
987 VALUE subst
= rb_ary_new_capa(len
);
988 RUBY_ASSERT(ARY_EMBED_P(subst
));
990 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR(ary
));
991 ARY_SET_EMBED_LEN(subst
, len
);
995 return rb_ary_increment_share(ary_make_shared(ary
));
1000 rb_assoc_new(VALUE car
, VALUE cdr
)
1002 return rb_ary_new3(2, car
, cdr
);
1006 rb_to_array_type(VALUE ary
)
1008 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1010 #define to_ary rb_to_array_type
1013 rb_check_array_type(VALUE ary
)
1015 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1019 rb_check_to_array(VALUE ary
)
1021 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1025 rb_to_array(VALUE ary
)
1027 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1032 * Array.try_convert(object) -> object, new_array, or nil
1034 * Attempts to return an array, based on the given +object+.
1036 * If +object+ is an array, returns +object+.
1038 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1039 * calls <tt>object.to_ary</tt>:
1040 * if the return value is an array or +nil+, returns that value;
1041 * if not, raises TypeError.
1043 * Otherwise returns +nil+.
1045 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1049 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1051 return rb_check_array_type(ary
);
1056 rb_ary_s_new(int argc
, VALUE
*argv
, VALUE klass
)
1060 if (klass
== rb_cArray
) {
1062 if (argc
> 0 && FIXNUM_P(argv
[0])) {
1063 size
= FIX2LONG(argv
[0]);
1064 if (size
< 0) size
= 0;
1067 ary
= ary_new(klass
, size
);
1069 rb_obj_call_init_kw(ary
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
1072 ary
= rb_class_new_instance_pass_kw(argc
, argv
, klass
);
1080 * Array.new -> new_empty_array
1081 * Array.new(array) -> new_array
1082 * Array.new(size, default_value = nil) -> new_array
1083 * Array.new(size = 0) {|index| ... } -> new_array
1085 * Returns a new array.
1087 * With no block and no argument given, returns a new empty array:
1091 * With no block and array argument given, returns a new array with the same elements:
1093 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1095 * With no block and integer argument given, returns a new array containing
1096 * that many instances of the given +default_value+:
1098 * Array.new(0) # => []
1099 * Array.new(3) # => [nil, nil, nil]
1100 * Array.new(2, 3) # => [3, 3]
1102 * With a block given, returns an array of the given +size+;
1103 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1104 * the element at that +index+ in the returned array is the blocks return value:
1106 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1108 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1110 * array = Array.new(2, {})
1111 * array # => [{}, {}]
1113 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1115 * If you want the elements of the array to be distinct, you should pass a block:
1117 * array = Array.new(2) { {} }
1118 * array # => [{}, {}]
1120 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1122 * Raises TypeError if the first argument is not either an array
1123 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1124 * Raises ArgumentError if the first argument is a negative integer.
1126 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1130 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1138 RUBY_ASSERT(ARY_EMBED_P(ary
));
1139 RUBY_ASSERT(ARY_EMBED_LEN(ary
) == 0);
1140 if (rb_block_given_p()) {
1141 rb_warning("given block not used");
1145 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1146 if (argc
== 1 && !FIXNUM_P(size
)) {
1147 val
= rb_check_array_type(size
);
1149 rb_ary_replace(ary
, val
);
1154 len
= NUM2LONG(size
);
1155 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1157 rb_raise(rb_eArgError
, "negative array size");
1159 if (len
> ARY_MAX_SIZE
) {
1160 rb_raise(rb_eArgError
, "array size too big");
1162 /* recheck after argument conversion */
1164 ary_resize_capa(ary
, len
);
1165 if (rb_block_given_p()) {
1169 rb_warn("block supersedes default value argument");
1171 for (i
=0; i
<len
; i
++) {
1172 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1173 ARY_SET_LEN(ary
, i
+ 1);
1177 ary_memfill(ary
, 0, len
, val
);
1178 ARY_SET_LEN(ary
, len
);
1184 * Returns a new array, populated with the given objects:
1186 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1188 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1190 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1194 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1196 VALUE ary
= ary_new(klass
, argc
);
1197 if (argc
> 0 && argv
) {
1198 ary_memcpy(ary
, 0, argc
, argv
);
1199 ARY_SET_LEN(ary
, argc
);
1206 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1208 long len
= RARRAY_LEN(ary
);
1213 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1217 else if (idx
>= ARY_MAX_SIZE
) {
1218 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1222 if (idx
>= ARY_CAPA(ary
)) {
1223 ary_double_capa(ary
, idx
);
1226 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1230 ARY_SET_LEN(ary
, idx
+ 1);
1232 ARY_SET(ary
, idx
, val
);
1236 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1238 RUBY_ASSERT(offset
>= 0);
1239 RUBY_ASSERT(len
>= 0);
1240 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1242 VALUE result
= ary_alloc_heap(klass
);
1243 size_t embed_capa
= ary_embed_capa(result
);
1244 if ((size_t)len
<= embed_capa
) {
1245 FL_SET_EMBED(result
);
1246 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR(ary
) + offset
);
1247 ARY_SET_EMBED_LEN(result
, len
);
1250 VALUE shared
= ary_make_shared(ary
);
1252 /* The ary_make_shared call may allocate, which can trigger a GC
1253 * compaction. This can cause the array to be embedded because it has
1255 FL_UNSET_EMBED(result
);
1257 ARY_SET_PTR(result
, RARRAY_CONST_PTR(ary
));
1258 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1259 rb_ary_set_shared(result
, shared
);
1261 ARY_INCREASE_PTR(result
, offset
);
1262 ARY_SET_LEN(result
, len
);
1272 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1274 RUBY_ASSERT(offset
>= 0);
1275 RUBY_ASSERT(len
>= 0);
1276 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1277 RUBY_ASSERT(step
!= 0);
1279 const long orig_len
= len
;
1281 if (step
> 0 && step
>= len
) {
1282 VALUE result
= ary_new(klass
, 1);
1283 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1284 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1286 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1287 ARY_SET_EMBED_LEN(result
, 1);
1290 else if (step
< 0 && step
< -len
) {
1294 long ustep
= (step
< 0) ? -step
: step
;
1295 len
= roomof(len
, ustep
);
1298 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1300 VALUE result
= ary_new(klass
, len
);
1301 if (ARY_EMBED_P(result
)) {
1302 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1303 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1305 for (i
= 0; i
< len
; ++i
) {
1306 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1309 ARY_SET_EMBED_LEN(result
, len
);
1312 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1314 RARRAY_PTR_USE(result
, ptr
, {
1315 for (i
= 0; i
< len
; ++i
) {
1316 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1320 ARY_SET_LEN(result
, len
);
1327 ary_make_shared_copy(VALUE ary
)
1329 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1332 enum ary_take_pos_flags
1339 ary_take_first_or_last_n(VALUE ary
, long n
, enum ary_take_pos_flags last
)
1341 long len
= RARRAY_LEN(ary
);
1348 rb_raise(rb_eArgError
, "negative array size");
1353 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1357 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1359 argc
= rb_check_arity(argc
, 0, 1);
1360 /* the case optional argument is omitted should be handled in
1361 * callers of this function. if another arity case is added,
1362 * this arity check needs to rewrite. */
1363 RUBY_ASSERT_ALWAYS(argc
== 1);
1364 return ary_take_first_or_last_n(ary
, NUM2LONG(argv
[0]), last
);
1369 * self << object -> self
1371 * Appends +object+ as the last element in +self+; returns +self+:
1373 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1375 * Appends +object+ as a single element, even if it is another array:
1377 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1379 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1383 rb_ary_push(VALUE ary
, VALUE item
)
1385 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1386 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1387 RARRAY_PTR_USE(ary
, ptr
, {
1388 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1390 ARY_SET_LEN(ary
, idx
+ 1);
1396 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1398 long oldlen
= RARRAY_LEN(ary
);
1399 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1400 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1401 ARY_SET_LEN(ary
, oldlen
+ len
);
1407 * push(*objects) -> self
1408 * append(*objects) -> self
1410 * Appends each argument in +objects+ to +self+; returns +self+:
1412 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1413 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1415 * Appends each argument as a single element, even if it is another array:
1417 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1418 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1420 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1424 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1426 return rb_ary_cat(ary
, argv
, argc
);
1430 rb_ary_pop(VALUE ary
)
1433 rb_ary_modify_check(ary
);
1434 n
= RARRAY_LEN(ary
);
1435 if (n
== 0) return Qnil
;
1436 if (ARY_OWNS_HEAP_P(ary
) &&
1437 n
* 3 < ARY_CAPA(ary
) &&
1438 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1440 ary_resize_capa(ary
, n
* 2);
1443 ARY_SET_LEN(ary
, n
);
1445 return RARRAY_AREF(ary
, n
);
1450 * pop -> object or nil
1451 * pop(count) -> new_array
1453 * Removes and returns trailing elements of +self+.
1455 * With no argument given, removes and returns the last element, if available;
1456 * otherwise returns +nil+:
1458 * a = [:foo, 'bar', 2]
1460 * a # => [:foo, "bar"]
1463 * With non-negative integer argument +count+ given,
1464 * returns a new array containing the trailing +count+ elements of +self+, as available:
1466 * a = [:foo, 'bar', 2]
1467 * a.pop(2) # => ["bar", 2]
1470 * a = [:foo, 'bar', 2]
1471 * a.pop(50) # => [:foo, "bar", 2]
1474 * Related: Array#push;
1475 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1479 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1484 return rb_ary_pop(ary
);
1487 rb_ary_modify_check(ary
);
1488 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1489 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1495 rb_ary_shift(VALUE ary
)
1498 long len
= RARRAY_LEN(ary
);
1501 rb_ary_modify_check(ary
);
1505 top
= RARRAY_AREF(ary
, 0);
1507 rb_ary_behead(ary
, 1);
1514 * shift -> object or nil
1515 * shift(count) -> new_array or nil
1517 * Removes and returns leading elements from +self+.
1519 * With no argument, removes and returns one element, if available,
1520 * or +nil+ otherwise:
1527 * With non-negative numeric argument +count+ given,
1528 * removes and returns the first +count+ elements:
1531 * a.shift(2) # => [0, 1]
1533 * a.shift(1.1) # => [2]
1535 * a.shift(0) # => []
1538 * If +count+ is large,
1539 * removes and returns all elements:
1542 * a.shift(50) # => [0, 1, 2, 3]
1545 * If +self+ is empty, returns a new empty array.
1547 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1551 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1557 return rb_ary_shift(ary
);
1560 rb_ary_modify_check(ary
);
1561 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1562 n
= RARRAY_LEN(result
);
1563 rb_ary_behead(ary
,n
);
1569 rb_ary_behead(VALUE ary
, long n
)
1575 rb_ary_modify_check(ary
);
1577 if (!ARY_SHARED_P(ary
)) {
1578 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1579 RARRAY_PTR_USE(ary
, ptr
, {
1580 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1581 }); /* WB: no new reference */
1582 ARY_INCREASE_LEN(ary
, -n
);
1587 ary_mem_clear(ary
, 0, n
);
1588 ary_make_shared(ary
);
1590 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1591 ary_mem_clear(ary
, 0, n
);
1594 ARY_INCREASE_PTR(ary
, n
);
1595 ARY_INCREASE_LEN(ary
, -n
);
1602 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1604 if (head
- sharedp
< argc
) {
1605 long room
= capa
- len
- argc
;
1608 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1609 head
= sharedp
+ argc
+ room
;
1611 ARY_SET_PTR(ary
, head
- argc
);
1612 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1615 return ARY_SHARED_ROOT(ary
);
1619 ary_modify_for_unshift(VALUE ary
, int argc
)
1621 long len
= RARRAY_LEN(ary
);
1622 long new_len
= len
+ argc
;
1624 const VALUE
*head
, *sharedp
;
1627 capa
= ARY_CAPA(ary
);
1628 if (capa
- (capa
>> 6) <= new_len
) {
1629 ary_double_capa(ary
, new_len
);
1632 /* use shared array for big "queues" */
1633 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1636 /* make a room for unshifted items */
1637 capa
= ARY_CAPA(ary
);
1638 ary_make_shared(ary
);
1640 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1641 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1645 RARRAY_PTR_USE(ary
, ptr
, {
1646 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1655 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1657 long len
= RARRAY_LEN(ary
);
1658 long new_len
= len
+ argc
;
1660 if (len
> ARY_MAX_SIZE
- argc
) {
1661 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1663 else if (! ARY_SHARED_P(ary
)) {
1664 return ary_modify_for_unshift(ary
, argc
);
1667 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1668 long capa
= RARRAY_LEN(shared_root
);
1670 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1671 return ary_modify_for_unshift(ary
, argc
);
1673 else if (new_len
> capa
) {
1674 return ary_modify_for_unshift(ary
, argc
);
1677 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1678 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1680 rb_ary_modify_check(ary
);
1681 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1688 * unshift(*objects) -> self
1689 * prepend(*objects) -> self
1691 * Prepends the given +objects+ to +self+:
1693 * a = [:foo, 'bar', 2]
1694 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1696 * Related: Array#shift;
1697 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1701 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1703 long len
= RARRAY_LEN(ary
);
1707 rb_ary_modify_check(ary
);
1711 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1712 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1713 ARY_SET_LEN(ary
, len
+ argc
);
1718 rb_ary_unshift(VALUE ary
, VALUE item
)
1720 return rb_ary_unshift_m(1, &item
, ary
);
1723 /* faster version - use this if you don't need to treat negative offset */
1725 rb_ary_elt(VALUE ary
, long offset
)
1727 long len
= RARRAY_LEN(ary
);
1728 if (len
== 0) return Qnil
;
1729 if (offset
< 0 || len
<= offset
) {
1732 return RARRAY_AREF(ary
, offset
);
1736 rb_ary_entry(VALUE ary
, long offset
)
1738 return rb_ary_entry_internal(ary
, offset
);
1742 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1745 long alen
= RARRAY_LEN(ary
);
1747 if (beg
> alen
) return Qnil
;
1748 if (beg
< 0 || len
< 0) return Qnil
;
1750 if (alen
< len
|| alen
< beg
+ len
) {
1754 if (len
== 0) return ary_new(klass
, 0);
1756 rb_raise(rb_eArgError
, "slice step cannot be zero");
1758 return ary_make_partial(ary
, klass
, beg
, len
);
1760 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1764 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1766 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1769 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1773 * self[index] -> object or nil
1774 * self[start, length] -> object or nil
1775 * self[range] -> object or nil
1776 * self[aseq] -> object or nil
1777 * slice(index) -> object or nil
1778 * slice(start, length) -> object or nil
1779 * slice(range) -> object or nil
1780 * slice(aseq) -> object or nil
1782 * Returns elements from +self+; does not modify +self+.
1786 * a = [:foo, 'bar', 2]
1788 * # Single argument index: returns one element.
1789 * a[0] # => :foo # Zero-based index.
1790 * a[-1] # => 2 # Negative index counts backwards from end.
1792 * # Arguments start and length: returns an array.
1793 * a[1, 2] # => ["bar", 2]
1794 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1796 * # Single argument range: returns an array.
1797 * a[0..1] # => [:foo, "bar"]
1798 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1799 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1801 * When a single integer argument +index+ is given, returns the element at offset +index+:
1803 * a = [:foo, 'bar', 2]
1806 * a # => [:foo, "bar", 2]
1808 * If +index+ is negative, counts backwards from the end of +self+:
1810 * a = [:foo, 'bar', 2]
1814 * If +index+ is out of range, returns +nil+.
1816 * When two Integer arguments +start+ and +length+ are given,
1817 * returns a new array of size +length+ containing successive elements beginning at offset +start+:
1819 * a = [:foo, 'bar', 2]
1820 * a[0, 2] # => [:foo, "bar"]
1821 * a[1, 2] # => ["bar", 2]
1823 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1824 * returns all elements from offset +start+ to the end:
1826 * a = [:foo, 'bar', 2]
1827 * a[0, 4] # => [:foo, "bar", 2]
1828 * a[1, 3] # => ["bar", 2]
1831 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1832 * returns a new empty array.
1834 * If +length+ is negative, returns +nil+.
1836 * When a single Range argument +range+ is given,
1837 * treats <tt>range.min</tt> as +start+ above
1838 * and <tt>range.size</tt> as +length+ above:
1840 * a = [:foo, 'bar', 2]
1841 * a[0..1] # => [:foo, "bar"]
1842 * a[1..2] # => ["bar", 2]
1844 * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
1846 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1848 * a = [:foo, 'bar', 2]
1849 * a[0..-1] # => [:foo, "bar", 2]
1850 * a[0..-2] # => [:foo, "bar"]
1851 * a[0..-3] # => [:foo]
1853 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1855 * a = [:foo, 'bar', 2]
1857 * a[-2..2] # => ["bar", 2]
1858 * a[-3..2] # => [:foo, "bar", 2]
1860 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1862 * a = [:foo, 'bar', 2]
1867 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1868 * returns an array of elements corresponding to the indexes produced by
1871 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1872 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1874 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1875 * is larger than array size, throws RangeError.
1877 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1878 * a[(1..11).step(2)]
1879 * # RangeError (((1..11).step(2)) out of range)
1881 * # RangeError (((7..).step(2)) out of range)
1883 * If given a single argument, and its type is not one of the listed, tries to
1884 * convert it to Integer, and raises if it is impossible:
1886 * a = [:foo, 'bar', 2]
1887 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1890 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1894 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1896 rb_check_arity(argc
, 1, 2);
1898 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1900 return rb_ary_aref1(ary
, argv
[0]);
1904 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1906 long beg
= NUM2LONG(b
);
1907 long len
= NUM2LONG(e
);
1909 beg
+= RARRAY_LEN(ary
);
1911 return rb_ary_subseq(ary
, beg
, len
);
1915 rb_ary_aref1(VALUE ary
, VALUE arg
)
1917 long beg
, len
, step
;
1919 /* special case - speeding up */
1920 if (FIXNUM_P(arg
)) {
1921 return rb_ary_entry(ary
, FIX2LONG(arg
));
1923 /* check if idx is Range or ArithmeticSequence */
1924 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1930 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1933 return rb_ary_entry(ary
, NUM2LONG(arg
));
1938 * at(index) -> object or nil
1940 * Returns the element of +self+ specified by the given +index+
1941 * or +nil+ if there is no such element;
1942 * +index+ must be an
1943 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1945 * For non-negative +index+, returns the element of +self+ at offset +index+:
1947 * a = [:foo, 'bar', 2]
1952 * For negative +index+, counts backwards from the end of +self+:
1954 * a.at(-2) # => "bar"
1956 * Related: Array#[];
1957 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1961 rb_ary_at(VALUE ary
, VALUE pos
)
1963 return rb_ary_entry(ary
, NUM2LONG(pos
));
1968 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1971 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1972 return RARRAY_AREF(ary
, 0);
1975 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1981 ary_first(VALUE self
)
1983 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1987 ary_last(VALUE self
)
1989 long len
= RARRAY_LEN(self
);
1990 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1994 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1997 return ary_last(ary
);
2000 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
2006 * fetch(index) -> element
2007 * fetch(index, default_value) -> element or default_value
2008 * fetch(index) {|index| ... } -> element or block_return_value
2010 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2011 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2013 * With the single argument +index+ and no block,
2014 * returns the element at offset +index+:
2016 * a = [:foo, 'bar', 2]
2017 * a.fetch(1) # => "bar"
2018 * a.fetch(1.1) # => "bar"
2020 * If +index+ is negative, counts from the end of the array:
2022 * a = [:foo, 'bar', 2]
2023 * a.fetch(-1) # => 2
2024 * a.fetch(-2) # => "bar"
2026 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2027 * returns +default_value+ if +index+ is out-of-range:
2029 * a = [:foo, 'bar', 2]
2030 * a.fetch(1, nil) # => "bar"
2031 * a.fetch(3, :foo) # => :foo
2033 * With argument +index+ and a block,
2034 * returns the element at offset +index+ if index is in range
2035 * (and the block is not called); otherwise calls the block with index and returns its return value:
2037 * a = [:foo, 'bar', 2]
2038 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2039 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2041 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2045 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
2051 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
2052 block_given
= rb_block_given_p();
2053 if (block_given
&& argc
== 2) {
2054 rb_warn("block supersedes default value argument");
2056 idx
= NUM2LONG(pos
);
2059 idx
+= RARRAY_LEN(ary
);
2061 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2062 if (block_given
) return rb_yield(pos
);
2064 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2065 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2069 return RARRAY_AREF(ary
, idx
);
2074 * find_index(object) -> integer or nil
2075 * find_index {|element| ... } -> integer or nil
2076 * find_index -> new_enumerator
2077 * index(object) -> integer or nil
2078 * index {|element| ... } -> integer or nil
2079 * index -> new_enumerator
2081 * Returns the zero-based integer index of a specified element, or +nil+.
2083 * With only argument +object+ given,
2084 * returns the index of the first element +element+
2085 * for which <tt>object == element</tt>:
2087 * a = [:foo, 'bar', 2, 'bar']
2088 * a.index('bar') # => 1
2090 * Returns +nil+ if no such element found.
2092 * With only a block given,
2093 * calls the block with each successive element;
2094 * returns the index of the first element for which the block returns a truthy value:
2096 * a = [:foo, 'bar', 2, 'bar']
2097 * a.index {|element| element == 'bar' } # => 1
2099 * Returns +nil+ if the block never returns a truthy value.
2101 * With neither an argument nor a block given, returns a new Enumerator.
2103 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2107 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2113 RETURN_ENUMERATOR(ary
, 0, 0);
2114 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2115 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2121 rb_check_arity(argc
, 0, 1);
2123 if (rb_block_given_p())
2124 rb_warn("given block not used");
2125 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2126 VALUE e
= RARRAY_AREF(ary
, i
);
2127 if (rb_equal(e
, val
)) {
2136 * rindex(object) -> integer or nil
2137 * rindex {|element| ... } -> integer or nil
2138 * rindex -> new_enumerator
2140 * Returns the index of the last element for which <tt>object == element</tt>.
2142 * With argument +object+ given, returns the index of the last such element found:
2144 * a = [:foo, 'bar', 2, 'bar']
2145 * a.rindex('bar') # => 3
2147 * Returns +nil+ if no such object found.
2149 * With a block given, calls the block with each successive element;
2150 * returns the index of the last element for which the block returns a truthy value:
2152 * a = [:foo, 'bar', 2, 'bar']
2153 * a.rindex {|element| element == 'bar' } # => 3
2155 * Returns +nil+ if the block never returns a truthy value.
2157 * When neither an argument nor a block is given, returns a new Enumerator.
2159 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2163 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2166 long i
= RARRAY_LEN(ary
), len
;
2169 RETURN_ENUMERATOR(ary
, 0, 0);
2171 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2173 if (i
> (len
= RARRAY_LEN(ary
))) {
2179 rb_check_arity(argc
, 0, 1);
2181 if (rb_block_given_p())
2182 rb_warn("given block not used");
2184 VALUE e
= RARRAY_AREF(ary
, i
);
2185 if (rb_equal(e
, val
)) {
2188 if (i
> RARRAY_LEN(ary
)) {
2196 rb_ary_to_ary(VALUE obj
)
2198 VALUE tmp
= rb_check_array_type(obj
);
2200 if (!NIL_P(tmp
)) return tmp
;
2201 return rb_ary_new3(1, obj
);
2205 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2210 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2211 olen
= RARRAY_LEN(ary
);
2215 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2219 if (olen
< len
|| olen
< beg
+ len
) {
2224 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2225 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2230 if (beg
> ARY_MAX_SIZE
- rlen
) {
2231 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2233 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2235 ary_mem_clear(ary
, olen
, beg
- olen
);
2237 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2238 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2240 ARY_SET_LEN(ary
, len
);
2245 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2246 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2249 alen
= olen
+ rlen
- len
;
2250 if (alen
>= ARY_CAPA(ary
)) {
2251 ary_double_capa(ary
, alen
);
2255 RARRAY_PTR_USE(ary
, ptr
,
2256 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2257 VALUE
, olen
- (beg
+ len
)));
2258 ARY_SET_LEN(ary
, alen
);
2262 rb_gc_writebarrier_remember(ary
);
2265 /* In this case, we're copying from a region in this array, so
2266 * we don't need to fire the write barrier. */
2267 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2270 /* do not use RARRAY_PTR() because it can causes GC.
2271 * ary can contain T_NONE object because it is not cleared.
2273 RARRAY_PTR_USE(ary
, ptr
,
2274 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2280 rb_ary_set_len(VALUE ary
, long len
)
2284 rb_ary_modify_check(ary
);
2285 if (ARY_SHARED_P(ary
)) {
2286 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2288 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2289 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2291 ARY_SET_LEN(ary
, len
);
2295 rb_ary_resize(VALUE ary
, long len
)
2300 olen
= RARRAY_LEN(ary
);
2301 if (len
== olen
) return ary
;
2302 if (len
> ARY_MAX_SIZE
) {
2303 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2306 if (len
> ARY_CAPA(ary
)) {
2307 ary_double_capa(ary
, len
);
2309 ary_mem_clear(ary
, olen
, len
- olen
);
2310 ARY_SET_LEN(ary
, len
);
2312 else if (ARY_EMBED_P(ary
)) {
2313 ARY_SET_EMBED_LEN(ary
, len
);
2315 else if (len
<= ary_embed_capa(ary
)) {
2316 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2317 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2318 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2322 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2323 ARY_SET_EMBED_LEN(ary
, len
);
2325 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2328 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2329 size_t new_capa
= ary_heap_realloc(ary
, len
);
2330 ARY_SET_CAPA(ary
, new_capa
);
2332 ARY_SET_HEAP_LEN(ary
, len
);
2339 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2341 rb_ary_store(ary
, key
, val
);
2346 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2348 VALUE rpl
= rb_ary_to_ary(val
);
2349 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2356 * self[index] = object -> object
2357 * self[start, length] = object -> object
2358 * self[range] = object -> object
2360 * Assigns elements in +self+, based on the given +object+; returns +object+.
2364 * a_orig = [:foo, 'bar', 2]
2366 * # With argument index.
2368 * a[0] = 'foo' # => "foo"
2369 * a # => ["foo", "bar", 2]
2371 * a[7] = 'foo' # => "foo"
2372 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2374 * # With arguments start and length.
2376 * a[0, 2] = 'foo' # => "foo"
2379 * a[6, 50] = 'foo' # => "foo"
2380 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2382 * # With argument range.
2384 * a[0..1] = 'foo' # => "foo"
2387 * a[6..50] = 'foo' # => "foo"
2388 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2390 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2392 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2394 * a = [:foo, 'bar', 2]
2395 * a[0] = 'foo' # => "foo"
2396 * a # => ["foo", "bar", 2]
2398 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2400 * a = [:foo, 'bar', 2]
2401 * a[7] = 'foo' # => "foo"
2402 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2404 * If +index+ is negative, counts backwards from the end of the array:
2406 * a = [:foo, 'bar', 2]
2407 * a[-1] = 'two' # => "two"
2408 * a # => [:foo, "bar", "two"]
2410 * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
2411 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2412 * and assigns +object+ at offset +start+:
2414 * a = [:foo, 'bar', 2]
2415 * a[0, 2] = 'foo' # => "foo"
2418 * If +start+ is negative, counts backwards from the end of the array:
2420 * a = [:foo, 'bar', 2]
2421 * a[-2, 2] = 'foo' # => "foo"
2422 * a # => [:foo, "foo"]
2424 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2425 * extends the array with +nil+, assigns +object+ at offset +start+,
2426 * and ignores +length+:
2428 * a = [:foo, 'bar', 2]
2429 * a[6, 50] = 'foo' # => "foo"
2430 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2432 * If +length+ is zero, shifts elements at and following offset +start+
2433 * and assigns +object+ at offset +start+:
2435 * a = [:foo, 'bar', 2]
2436 * a[1, 0] = 'foo' # => "foo"
2437 * a # => [:foo, "foo", "bar", 2]
2439 * If +length+ is too large for the existing array, does not extend the array:
2441 * a = [:foo, 'bar', 2]
2442 * a[1, 5] = 'foo' # => "foo"
2443 * a # => [:foo, "foo"]
2445 * When Range argument +range+ is given and +object+ is not an array,
2446 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2447 * and assigns +object+ at offset +start+:
2449 * a = [:foo, 'bar', 2]
2450 * a[0..1] = 'foo' # => "foo"
2453 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2455 * a = [:foo, 'bar', 2]
2456 * a[-2..2] = 'foo' # => "foo"
2457 * a # => [:foo, "foo"]
2459 * If the array length is less than <tt>range.begin</tt>,
2460 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2461 * and ignores +length+:
2463 * a = [:foo, 'bar', 2]
2464 * a[6..50] = 'foo' # => "foo"
2465 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2467 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2468 * and assigns +object+ at offset +start+:
2470 * a = [:foo, 'bar', 2]
2471 * a[1..0] = 'foo' # => "foo"
2472 * a # => [:foo, "foo", "bar", 2]
2474 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2475 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2477 * a = [:foo, 'bar', 2]
2478 * a[1..-1] = 'foo' # => "foo"
2479 * a # => [:foo, "foo"]
2480 * a = [:foo, 'bar', 2]
2481 * a[1..-2] = 'foo' # => "foo"
2482 * a # => [:foo, "foo", 2]
2483 * a = [:foo, 'bar', 2]
2484 * a[1..-3] = 'foo' # => "foo"
2485 * a # => [:foo, "foo", "bar", 2]
2486 * a = [:foo, 'bar', 2]
2488 * If <tt>range.end</tt> is too large for the existing array,
2489 * replaces array elements, but does not extend the array with +nil+ values:
2491 * a = [:foo, 'bar', 2]
2492 * a[1..5] = 'foo' # => "foo"
2493 * a # => [:foo, "foo"]
2495 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2499 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2501 long offset
, beg
, len
;
2503 rb_check_arity(argc
, 2, 3);
2504 rb_ary_modify_check(ary
);
2506 beg
= NUM2LONG(argv
[0]);
2507 len
= NUM2LONG(argv
[1]);
2508 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2510 if (FIXNUM_P(argv
[0])) {
2511 offset
= FIX2LONG(argv
[0]);
2512 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2514 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2515 /* check if idx is Range */
2516 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2519 offset
= NUM2LONG(argv
[0]);
2520 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2525 * insert(index, *objects) -> self
2527 * Inserts the given +objects+ as elements of +self+;
2530 * When +index+ is non-negative, inserts +objects+
2531 * _before_ the element at offset +index+:
2533 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2534 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2536 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2538 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2539 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2541 * When +index+ is negative, inserts +objects+
2542 * _after_ the element at offset <tt>index + self.size</tt>:
2544 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2545 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2547 * With no +objects+ given, does nothing:
2549 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2550 * a.insert(1) # => ["a", "b", "c"]
2551 * a.insert(50) # => ["a", "b", "c"]
2552 * a.insert(-50) # => ["a", "b", "c"]
2554 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2556 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2560 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2564 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2565 rb_ary_modify_check(ary
);
2566 pos
= NUM2LONG(argv
[0]);
2567 if (argc
== 1) return ary
;
2569 pos
= RARRAY_LEN(ary
);
2572 long minpos
= -RARRAY_LEN(ary
) - 1;
2574 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2579 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2584 rb_ary_length(VALUE ary
);
2587 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2589 return rb_ary_length(ary
);
2592 // Primitive to avoid a race condition in Array#each.
2593 // Return `true` and write `value` and `index` if the element exists.
2595 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2597 long i
= NUM2LONG(*index
);
2598 if (i
>= RARRAY_LEN(self
)) {
2601 *value
= RARRAY_AREF(self
, i
);
2602 *index
= LONG2NUM(i
+ 1);
2608 * each {|element| ... } -> self
2609 * each -> new_enumerator
2611 * With a block given, iterates over the elements of +self+,
2612 * passing each element to the block;
2615 * a = [:foo, 'bar', 2]
2616 * a.each {|element| puts "#{element.class} #{element}" }
2624 * Allows the array to be modified during iteration:
2626 * a = [:foo, 'bar', 2]
2627 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2634 * With no block given, returns a new Enumerator.
2636 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2640 rb_ary_each(VALUE ary
)
2644 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2645 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2646 rb_yield(RARRAY_AREF(ary
, i
));
2653 * each_index {|index| ... } -> self
2654 * each_index -> new_enumerator
2656 * With a block given, iterates over the elements of +self+,
2657 * passing each <i>array index</i> to the block;
2660 * a = [:foo, 'bar', 2]
2661 * a.each_index {|index| puts "#{index} #{a[index]}" }
2669 * Allows the array to be modified during iteration:
2671 * a = [:foo, 'bar', 2]
2672 * a.each_index {|index| puts index; a.clear if index > 0 }
2680 * With no block given, returns a new Enumerator.
2682 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2686 rb_ary_each_index(VALUE ary
)
2689 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2691 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2692 rb_yield(LONG2NUM(i
));
2699 * reverse_each {|element| ... } -> self
2700 * reverse_each -> Enumerator
2702 * When a block given, iterates backwards over the elements of +self+,
2703 * passing, in reverse order, each element to the block;
2707 * [0, 1, 2].reverse_each {|element| a.push(element) }
2710 * Allows the array to be modified during iteration:
2712 * a = ['a', 'b', 'c']
2713 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2716 * When no block given, returns a new Enumerator.
2718 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2722 rb_ary_reverse_each(VALUE ary
)
2726 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2727 len
= RARRAY_LEN(ary
);
2730 rb_yield(RARRAY_AREF(ary
, len
));
2731 nlen
= RARRAY_LEN(ary
);
2744 * Returns the count of elements in +self+:
2746 * [0, 1, 2].length # => 3
2749 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2753 rb_ary_length(VALUE ary
)
2755 long len
= RARRAY_LEN(ary
);
2756 return LONG2NUM(len
);
2761 * empty? -> true or false
2763 * Returns +true+ if the count of elements in +self+ is zero,
2764 * +false+ otherwise.
2766 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2770 rb_ary_empty_p(VALUE ary
)
2772 return RBOOL(RARRAY_LEN(ary
) == 0);
2776 rb_ary_dup(VALUE ary
)
2778 long len
= RARRAY_LEN(ary
);
2779 VALUE dup
= rb_ary_new2(len
);
2780 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2781 ARY_SET_LEN(dup
, len
);
2789 rb_ary_resurrect(VALUE ary
)
2791 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2794 extern VALUE rb_output_fs
;
2796 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2799 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2801 VALUE
*arg
= (VALUE
*)argp
;
2804 VALUE result
= arg
[2];
2805 int *first
= (int *)arg
[3];
2808 rb_raise(rb_eArgError
, "recursive array join");
2811 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2817 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2822 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2823 for (i
=0; i
<max
; i
++) {
2824 val
= RARRAY_AREF(ary
, i
);
2825 if (!RB_TYPE_P(val
, T_STRING
)) break;
2826 if (i
> 0 && !NIL_P(sep
))
2827 rb_str_buf_append(result
, sep
);
2828 rb_str_buf_append(result
, val
);
2834 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2836 rb_str_buf_append(dst
, src
);
2838 rb_enc_copy(dst
, src
);
2844 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2847 rb_raise(rb_eArgError
, "recursive array join");
2856 args
[3] = (VALUE
)first
;
2857 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2862 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2866 for (; i
<RARRAY_LEN(ary
); i
++) {
2867 if (i
> 0 && !NIL_P(sep
))
2868 rb_str_buf_append(result
, sep
);
2870 val
= RARRAY_AREF(ary
, i
);
2871 if (RB_TYPE_P(val
, T_STRING
)) {
2872 ary_join_1_str(result
, val
, first
);
2874 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2875 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2877 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2878 ary_join_1_str(result
, tmp
, first
);
2880 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2881 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2884 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2890 rb_ary_join(VALUE ary
, VALUE sep
)
2893 VALUE val
, tmp
, result
;
2895 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2899 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2901 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2902 val
= RARRAY_AREF(ary
, i
);
2903 tmp
= rb_check_string_type(val
);
2905 if (NIL_P(tmp
) || tmp
!= val
) {
2907 long n
= RARRAY_LEN(ary
);
2909 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2910 rb_enc_associate(result
, rb_usascii_encoding());
2911 i
= ary_join_0(ary
, sep
, i
, result
);
2913 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2917 len
+= RSTRING_LEN(tmp
);
2920 result
= rb_str_new(0, len
);
2921 rb_str_set_len(result
, 0);
2923 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2930 * join(separator = $,) -> new_string
2932 * Returns the new string formed by joining the converted elements of +self+;
2933 * for each element +element+:
2935 * - Converts recursively using <tt>element.join(separator)</tt>
2936 * if +element+ is a <tt>kind_of?(Array)</tt>.
2937 * - Otherwise, converts using <tt>element.to_s</tt>.
2939 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2941 * a = [:foo, 'bar', 2]
2943 * a.join # => "foobar2"
2945 * With string argument +separator+ given, joins using that separator:
2947 * a = [:foo, 'bar', 2]
2948 * a.join("\n") # => "foo\nbar\n2"
2950 * Joins recursively for nested arrays:
2952 * a = [:foo, [:bar, [:baz, :bat]]]
2953 * a.join # => "foobarbazbat"
2955 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2958 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2962 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2965 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2969 return rb_ary_join(ary
, sep
);
2973 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2978 if (recur
) return rb_usascii_str_new_cstr("[...]");
2979 str
= rb_str_buf_new2("[");
2980 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2981 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2982 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2983 else rb_enc_copy(str
, s
);
2984 rb_str_buf_append(str
, s
);
2986 rb_str_buf_cat2(str
, "]");
2992 * inspect -> new_string
2993 * to_s -> new_string
2995 * Returns the new string formed by calling method <tt>#inspect</tt>
2996 * on each array element:
2998 * a = [:foo, 'bar', 2]
2999 * a.inspect # => "[:foo, \"bar\", 2]"
3001 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3005 rb_ary_inspect(VALUE ary
)
3007 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
3008 return rb_exec_recursive(inspect_ary
, ary
, 0);
3012 rb_ary_to_s(VALUE ary
)
3014 return rb_ary_inspect(ary
);
3019 * to_a -> self or new_array
3021 * When +self+ is an instance of \Array, returns +self+.
3023 * Otherwise, returns a new array containing the elements of +self+:
3025 * class MyArray < Array; end
3026 * my_a = MyArray.new(['foo', 'bar', 'two'])
3028 * a # => ["foo", "bar", "two"]
3029 * a.class # => Array # Not MyArray.
3031 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3035 rb_ary_to_a(VALUE ary
)
3037 if (rb_obj_class(ary
) != rb_cArray
) {
3038 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
3039 rb_ary_replace(dup
, ary
);
3048 * to_h {|element| ... } -> new_hash
3050 * Returns a new hash formed from +self+.
3052 * With no block given, each element of +self+ must be a 2-element sub-array;
3053 * forms each sub-array into a key-value pair in the new hash:
3055 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3056 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3059 * With a block given, the block must return a 2-element array;
3060 * calls the block with each element of +self+;
3061 * forms each returned array into a key-value pair in the returned hash:
3063 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3064 * a.to_h {|element| [element, element.class] }
3065 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3067 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3071 rb_ary_to_h(VALUE ary
)
3074 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
3075 int block_given
= rb_block_given_p();
3077 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3078 const VALUE e
= rb_ary_elt(ary
, i
);
3079 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3080 const VALUE key_value_pair
= rb_check_array_type(elt
);
3081 if (NIL_P(key_value_pair
)) {
3082 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3083 rb_obj_class(elt
), i
);
3085 if (RARRAY_LEN(key_value_pair
) != 2) {
3086 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3087 i
, RARRAY_LEN(key_value_pair
));
3089 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3102 rb_ary_to_ary_m(VALUE ary
)
3108 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3118 rb_ary_reverse(VALUE ary
)
3121 long len
= RARRAY_LEN(ary
);
3125 RARRAY_PTR_USE(ary
, p1
, {
3126 p2
= p1
+ len
- 1; /* points last item */
3127 ary_reverse(p1
, p2
);
3128 }); /* WB: no new reference */
3137 * Reverses the order of the elements of +self+;
3141 * a.reverse! # => [2, 1, 0]
3144 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3148 rb_ary_reverse_bang(VALUE ary
)
3150 return rb_ary_reverse(ary
);
3155 * reverse -> new_array
3157 * Returns a new array containing the elements of +self+ in reverse order:
3159 * [0, 1, 2].reverse # => [2, 1, 0]
3161 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3165 rb_ary_reverse_m(VALUE ary
)
3167 long len
= RARRAY_LEN(ary
);
3168 VALUE dup
= rb_ary_new2(len
);
3171 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3172 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3173 do *p2
-- = *p1
++; while (--len
> 0);
3175 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3180 rotate_count(long cnt
, long len
)
3182 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3186 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3190 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3191 *(ptr
+ len
- 1) = tmp
;
3193 else if (cnt
== len
- 1) {
3194 VALUE tmp
= *(ptr
+ len
- 1);
3195 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3200 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3201 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3202 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3207 rb_ary_rotate(VALUE ary
, long cnt
)
3212 long len
= RARRAY_LEN(ary
);
3213 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3214 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3223 * rotate!(count = 1) -> self
3225 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3227 * With non-negative numeric +count+,
3228 * rotates +count+ elements from the beginning to the end:
3230 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3231 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3233 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3235 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3237 * If +count+ is zero, rotates no elements:
3239 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3241 * With a negative numeric +count+, rotates in the opposite direction,
3242 * from end to beginning:
3244 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3246 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3248 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3250 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3254 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3256 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3257 rb_ary_rotate(ary
, n
);
3263 * rotate(count = 1) -> new_array
3265 * Returns a new array formed from +self+ with elements
3266 * rotated from one end to the other.
3268 * With non-negative numeric +count+,
3269 * rotates elements from the beginning to the end:
3271 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3272 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3274 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3276 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3278 * With a +count+ of zero, rotates no elements:
3280 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3282 * With negative numeric +count+, rotates in the opposite direction,
3283 * from the end to the beginning:
3285 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3287 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3289 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3291 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3295 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3300 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3302 len
= RARRAY_LEN(ary
);
3303 rotated
= rb_ary_new2(len
);
3305 cnt
= rotate_count(cnt
, len
);
3306 ptr
= RARRAY_CONST_PTR(ary
);
3308 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3309 ary_memcpy(rotated
, len
, cnt
, ptr
);
3311 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3315 struct ary_sort_data
{
3321 sort_reentered(VALUE ary
)
3323 if (RBASIC(ary
)->klass
) {
3324 rb_raise(rb_eRuntimeError
, "sort reentered");
3330 sort_returned(struct ary_sort_data
*data
)
3332 if (rb_obj_frozen_p(data
->receiver
)) {
3333 rb_raise(rb_eFrozenError
, "array frozen during sort");
3335 sort_reentered(data
->ary
);
3339 sort_1(const void *ap
, const void *bp
, void *dummy
)
3341 struct ary_sort_data
*data
= dummy
;
3342 VALUE retval
= sort_reentered(data
->ary
);
3343 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3349 retval
= rb_yield_values2(2, args
);
3350 n
= rb_cmpint(retval
, a
, b
);
3351 sort_returned(data
);
3356 sort_2(const void *ap
, const void *bp
, void *dummy
)
3358 struct ary_sort_data
*data
= dummy
;
3359 VALUE retval
= sort_reentered(data
->ary
);
3360 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3363 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3364 if ((long)a
> (long)b
) return 1;
3365 if ((long)a
< (long)b
) return -1;
3368 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3369 return rb_str_cmp(a
, b
);
3371 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3372 return rb_float_cmp(a
, b
);
3375 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3376 n
= rb_cmpint(retval
, a
, b
);
3377 sort_returned(data
);
3385 * sort! {|a, b| ... } -> self
3387 * Like Array#sort, but returns +self+ with its elements sorted in place.
3389 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3393 rb_ary_sort_bang(VALUE ary
)
3396 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3397 if (RARRAY_LEN(ary
) > 1) {
3398 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3399 struct ary_sort_data data
;
3400 long len
= RARRAY_LEN(ary
);
3401 RBASIC_CLEAR_CLASS(tmp
);
3403 data
.receiver
= ary
;
3404 RARRAY_PTR_USE(tmp
, ptr
, {
3405 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3406 rb_block_given_p()?sort_1
:sort_2
, &data
);
3407 }); /* WB: no new reference */
3409 if (ARY_EMBED_P(tmp
)) {
3410 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3411 rb_ary_unshare(ary
);
3414 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3415 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3417 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3418 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3421 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3422 FL_UNSET_SHARED(ary
);
3423 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3426 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3427 if (ARY_EMBED_P(ary
)) {
3428 FL_UNSET_EMBED(ary
);
3430 else if (ARY_SHARED_P(ary
)) {
3431 /* ary might be destructively operated in the given block */
3432 rb_ary_unshare(ary
);
3437 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3438 ARY_SET_HEAP_LEN(ary
, len
);
3439 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3441 /* tmp was lost ownership for the ptr */
3442 FL_UNSET(tmp
, FL_FREEZE
);
3444 ARY_SET_EMBED_LEN(tmp
, 0);
3445 FL_SET(tmp
, FL_FREEZE
);
3447 /* tmp will be GC'ed. */
3448 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3457 * sort {|a, b| ... } -> new_array
3459 * Returns a new array containing the elements of +self+, sorted.
3461 * With no block given, compares elements using operator <tt>#<=></tt>
3464 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3466 * With a block given, calls the block with each combination of pairs of elements from +self+;
3467 * for each pair +a+ and +b+, the block should return a numeric:
3469 * - Negative when +b+ is to follow +a+.
3470 * - Zero when +a+ and +b+ are equivalent.
3471 * - Positive when +a+ is to follow +b+.
3476 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3477 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3479 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3480 * and may be unstable.
3482 * See an example in Numeric#nonzero? for the idiom to sort more
3483 * complex structure.
3485 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3489 rb_ary_sort(VALUE ary
)
3491 ary
= rb_ary_dup(ary
);
3492 rb_ary_sort_bang(ary
);
3496 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3500 * bsearch {|element| ... } -> found_element or nil
3501 * bsearch -> new_enumerator
3503 * Returns the element from +self+ found by a binary search,
3504 * or +nil+ if the search found no suitable element.
3506 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3508 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3512 rb_ary_bsearch(VALUE ary
)
3514 VALUE index_result
= rb_ary_bsearch_index(ary
);
3516 if (FIXNUM_P(index_result
)) {
3517 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3519 return index_result
;
3524 * bsearch_index {|element| ... } -> integer or nil
3525 * bsearch_index -> new_enumerator
3527 * Returns the integer index of the element from +self+ found by a binary search,
3528 * or +nil+ if the search found no suitable element.
3530 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3532 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3536 rb_ary_bsearch_index(VALUE ary
)
3538 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3539 int smaller
= 0, satisfied
= 0;
3542 RETURN_ENUMERATOR(ary
, 0, 0);
3543 while (low
< high
) {
3544 mid
= low
+ ((high
- low
) / 2);
3545 val
= rb_ary_entry(ary
, mid
);
3548 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3549 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3551 else if (v
== Qtrue
) {
3555 else if (!RTEST(v
)) {
3558 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3559 const VALUE zero
= INT2FIX(0);
3560 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3561 case 0: return INT2FIX(mid
);
3562 case 1: smaller
= 0; break;
3563 case -1: smaller
= 1;
3567 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3568 " (must be numeric, true, false or nil)",
3578 if (!satisfied
) return Qnil
;
3579 return INT2FIX(low
);
3584 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3591 * sort_by! {|element| ... } -> self
3592 * sort_by! -> new_enumerator
3594 * With a block given, sorts the elements of +self+ in place;
3597 * Calls the block with each successive element;
3598 * sorts elements based on the values returned from the block:
3600 * a = ['aaaa', 'bbb', 'cc', 'd']
3601 * a.sort_by! {|element| element.size }
3602 * a # => ["d", "cc", "bbb", "aaaa"]
3604 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3606 * With no block given, returns a new Enumerator.
3608 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3612 rb_ary_sort_by_bang(VALUE ary
)
3616 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3618 if (RARRAY_LEN(ary
) > 1) {
3619 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3620 rb_ary_replace(ary
, sorted
);
3628 * collect {|element| ... } -> new_array
3629 * collect -> new_enumerator
3630 * map {|element| ... } -> new_array
3631 * map -> new_enumerator
3633 * With a block given, calls the block with each element of +self+;
3634 * returns a new array whose elements are the return values from the block:
3636 * a = [:foo, 'bar', 2]
3637 * a1 = a.map {|element| element.class }
3638 * a1 # => [Symbol, String, Integer]
3640 * With no block given, returns a new Enumerator.
3642 * Related: #collect!;
3643 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3647 rb_ary_collect(VALUE ary
)
3652 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3653 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3654 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3655 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3663 * collect! {|element| ... } -> new_array
3664 * collect! -> new_enumerator
3665 * map! {|element| ... } -> new_array
3666 * map! -> new_enumerator
3668 * With a block given, calls the block with each element of +self+
3669 * and replaces the element with the block's return value;
3672 * a = [:foo, 'bar', 2]
3673 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3675 * With no block given, returns a new Enumerator.
3677 * Related: #collect;
3678 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3682 rb_ary_collect_bang(VALUE ary
)
3686 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3688 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3689 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3695 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3697 VALUE result
= rb_ary_new2(argc
);
3698 long beg
, len
, i
, j
;
3700 for (i
=0; i
<argc
; i
++) {
3701 if (FIXNUM_P(argv
[i
])) {
3702 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3705 /* check if idx is Range */
3706 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3707 long end
= olen
< beg
+len
? olen
: beg
+len
;
3708 for (j
= beg
; j
< end
; j
++) {
3709 rb_ary_push(result
, (*func
)(obj
, j
));
3712 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3715 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3721 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3724 if (FIXNUM_P(idx
)) {
3725 beg
= FIX2LONG(idx
);
3727 /* check if idx is Range */
3728 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3730 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3731 const long end
= beg
+ len
;
3732 const long prevlen
= RARRAY_LEN(result
);
3734 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3737 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3743 beg
= NUM2LONG(idx
);
3745 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3750 * values_at(*specifiers) -> new_array
3752 * Returns elements from +self+ in a new array; does not modify +self+.
3754 * The objects included in the returned array are the elements of +self+
3755 * selected by the given +specifiers+,
3756 * each of which must be a numeric index or a Range.
3760 * a = ['a', 'b', 'c', 'd']
3762 * # Index specifiers.
3763 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3764 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3765 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3767 * # Range specifiers.
3768 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
3769 * a.values_at(1...3) # => ["b", "c"] # End excluded.
3770 * a.values_at(3..1) # => [] # No such elements.
3772 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
3773 * a.values_at(-50..3) # Raises RangeError.
3775 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
3776 * a.values_at(1..-50) # => [] # No such elements.
3778 * # Mixture of specifiers.
3779 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
3781 * With no +specifiers+ given, returns a new empty array:
3783 * a = ['a', 'b', 'c', 'd']
3784 * a.values_at # => []
3786 * For each numeric specifier +index+, includes an element:
3788 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
3789 * includes the element at offset +index+:
3791 * a.values_at(0, 2) # => ["a", "c"]
3792 * a.values_at(0.1, 2.9) # => ["a", "c"]
3794 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
3795 * counts backwards from the end of +self+:
3797 * a.values_at(-1, -4) # => ["d", "a"]
3799 * The given indexes may be in any order, and may repeat:
3801 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
3803 * For each +index+ that is out-of-range, includes +nil+:
3805 * a.values_at(4, -5) # => [nil, nil]
3807 * For each Range specifier +range+, includes elements
3808 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
3810 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
3811 * are non-negative and in-range (less than <tt>self.size</tt>),
3812 * includes elements from index <tt>range.begin</tt>
3813 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
3814 * or through <tt>range.end</tt> (otherwise):
3816 * a.values_at(1..2) # => ["b", "c"]
3817 * a.values_at(1...2) # => ["b"]
3819 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
3820 * counts backwards from the end of +self+:
3822 * a.values_at(-2..3) # => ["c", "d"]
3824 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
3826 * a.values_at(-5..3) # Raises RangeError.
3828 * - If <tt>range.end</tt> is positive and out-of-range,
3829 * extends the returned array with +nil+ elements:
3831 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
3833 * - If <tt>range.end</tt> is negative and in-range,
3834 * counts backwards from the end of +self+:
3836 * a.values_at(1..-2) # => ["b", "c"]
3838 * - If <tt>range.end</tt> is negative and out-of-range,
3839 * returns an empty array:
3841 * a.values_at(1..-5) # => []
3843 * The given ranges may be in any order and may repeat:
3845 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
3847 * The given specifiers may be any mixture of indexes and ranges:
3849 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
3851 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3855 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3857 long i
, olen
= RARRAY_LEN(ary
);
3858 VALUE result
= rb_ary_new_capa(argc
);
3859 for (i
= 0; i
< argc
; ++i
) {
3860 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3869 * select {|element| ... } -> new_array
3870 * select -> new_enumerator
3871 * filter {|element| ... } -> new_array
3872 * filter -> new_enumerator
3874 * With a block given, calls the block with each element of +self+;
3875 * returns a new array containing those elements of +self+
3876 * for which the block returns a truthy value:
3878 * a = [:foo, 'bar', 2, :bam]
3879 * a.select {|element| element.to_s.start_with?('b') }
3880 * # => ["bar", :bam]
3882 * With no block given, returns a new Enumerator.
3884 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3888 rb_ary_select(VALUE ary
)
3893 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3894 result
= rb_ary_new2(RARRAY_LEN(ary
));
3895 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3896 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3897 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3903 struct select_bang_arg
{
3909 select_bang_i(VALUE a
)
3911 volatile struct select_bang_arg
*arg
= (void *)a
;
3912 VALUE ary
= arg
->ary
;
3915 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3916 VALUE v
= RARRAY_AREF(ary
, i1
);
3917 if (!RTEST(rb_yield(v
))) continue;
3919 rb_ary_store(ary
, i2
, v
);
3923 return (i1
== i2
) ? Qnil
: ary
;
3927 select_bang_ensure(VALUE a
)
3929 volatile struct select_bang_arg
*arg
= (void *)a
;
3930 VALUE ary
= arg
->ary
;
3931 long len
= RARRAY_LEN(ary
);
3932 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3934 if (i2
< len
&& i2
< i1
) {
3939 RARRAY_PTR_USE(ary
, ptr
, {
3940 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3943 ARY_SET_LEN(ary
, i2
+ tail
);
3950 * select! {|element| ... } -> self or nil
3951 * select! -> new_enumerator
3952 * filter! {|element| ... } -> self or nil
3953 * filter! -> new_enumerator
3955 * With a block given, calls the block with each element of +self+;
3956 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3958 * Returns +self+ if any elements were removed:
3960 * a = [:foo, 'bar', 2, :bam]
3961 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3963 * Returns +nil+ if no elements were removed.
3965 * With no block given, returns a new Enumerator.
3967 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3971 rb_ary_select_bang(VALUE ary
)
3973 struct select_bang_arg args
;
3975 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3979 args
.len
[0] = args
.len
[1] = 0;
3980 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3985 * keep_if {|element| ... } -> self
3986 * keep_if -> new_enumerator
3988 * With a block given, calls the block with each element of +self+;
3989 * removes the element from +self+ if the block does not return a truthy value:
3991 * a = [:foo, 'bar', 2, :bam]
3992 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3994 * With no block given, returns a new Enumerator.
3996 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4000 rb_ary_keep_if(VALUE ary
)
4002 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4003 rb_ary_select_bang(ary
);
4008 ary_resize_smaller(VALUE ary
, long len
)
4011 if (RARRAY_LEN(ary
) > len
) {
4012 ARY_SET_LEN(ary
, len
);
4013 if (len
* 2 < ARY_CAPA(ary
) &&
4014 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
4015 ary_resize_capa(ary
, len
* 2);
4022 * delete(object) -> last_removed_object
4023 * delete(object) {|element| ... } -> last_removed_object or block_return
4025 * Removes zero or more elements from +self+.
4027 * With no block given,
4028 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4029 * returns the last removed element:
4031 * a = [0, 1, 2, 2.0]
4032 * a.delete(2) # => 2.0
4035 * Returns +nil+ if no elements removed:
4037 * a.delete(2) # => nil
4039 * With a block given,
4040 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4042 * If any such elements are found, ignores the block
4043 * and returns the last removed element:
4045 * a = [0, 1, 2, 2.0]
4046 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4049 * If no such element is found, returns the block's return value:
4051 * a.delete(2) {|element| "Element #{element} not found." }
4052 * # => "Element 2 not found."
4054 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4058 rb_ary_delete(VALUE ary
, VALUE item
)
4063 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4064 VALUE e
= RARRAY_AREF(ary
, i1
);
4066 if (rb_equal(e
, item
)) {
4071 rb_ary_store(ary
, i2
, e
);
4075 if (RARRAY_LEN(ary
) == i2
) {
4076 if (rb_block_given_p()) {
4077 return rb_yield(item
);
4082 ary_resize_smaller(ary
, i2
);
4089 rb_ary_delete_same(VALUE ary
, VALUE item
)
4093 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4094 VALUE e
= RARRAY_AREF(ary
, i1
);
4100 rb_ary_store(ary
, i2
, e
);
4104 if (RARRAY_LEN(ary
) == i2
) {
4108 ary_resize_smaller(ary
, i2
);
4112 rb_ary_delete_at(VALUE ary
, long pos
)
4114 long len
= RARRAY_LEN(ary
);
4117 if (pos
>= len
) return Qnil
;
4120 if (pos
< 0) return Qnil
;
4124 del
= RARRAY_AREF(ary
, pos
);
4125 RARRAY_PTR_USE(ary
, ptr
, {
4126 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4128 ARY_INCREASE_LEN(ary
, -1);
4135 * delete_at(index) -> removed_object or nil
4137 * Removes the element of +self+ at the given +index+, which must be an
4138 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4140 * When +index+ is non-negative, deletes the element at offset +index+:
4142 * a = [:foo, 'bar', 2]
4143 * a.delete_at(1) # => "bar"
4146 * When +index+ is negative, counts backward from the end of the array:
4148 * a = [:foo, 'bar', 2]
4149 * a.delete_at(-2) # => "bar"
4152 * When +index+ is out of range, returns +nil+.
4154 * a = [:foo, 'bar', 2]
4155 * a.delete_at(3) # => nil
4156 * a.delete_at(-4) # => nil
4158 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4162 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4164 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4168 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4170 const long orig_len
= RARRAY_LEN(ary
);
4175 else if (pos
< -orig_len
) {
4181 else if (orig_len
< pos
) {
4184 if (orig_len
< pos
+ len
) {
4185 len
= orig_len
- pos
;
4188 return rb_ary_new2(0);
4191 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4192 rb_ary_splice(ary
, pos
, len
, 0, 0);
4199 * slice!(index) -> object or nil
4200 * slice!(start, length) -> new_array or nil
4201 * slice!(range) -> new_array or nil
4203 * Removes and returns elements from +self+.
4205 * With numeric argument +index+ given,
4206 * removes and returns the element at offset +index+:
4208 * a = ['a', 'b', 'c', 'd']
4209 * a.slice!(2) # => "c"
4210 * a # => ["a", "b", "d"]
4211 * a.slice!(2.1) # => "d"
4214 * If +index+ is negative, counts backwards from the end of +self+:
4216 * a = ['a', 'b', 'c', 'd']
4217 * a.slice!(-2) # => "c"
4218 * a # => ["a", "b", "d"]
4220 * If +index+ is out of range, returns +nil+.
4222 * With numeric arguments +start+ and +length+ given,
4223 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4224 * returns the removed objects in a new array:
4226 * a = ['a', 'b', 'c', 'd']
4227 * a.slice!(1, 2) # => ["b", "c"]
4229 * a.slice!(0.1, 1.1) # => ["a"]
4232 * If +start+ is negative, counts backwards from the end of +self+:
4234 * a = ['a', 'b', 'c', 'd']
4235 * a.slice!(-2, 1) # => ["c"]
4236 * a # => ["a", "b", "d"]
4238 * If +start+ is out-of-range, returns +nil+:
4240 * a = ['a', 'b', 'c', 'd']
4241 * a.slice!(5, 1) # => nil
4242 * a.slice!(-5, 1) # => nil
4244 * If <tt>start + length</tt> exceeds the array size,
4245 * removes and returns all elements from offset +start+ to the end:
4247 * a = ['a', 'b', 'c', 'd']
4248 * a.slice!(2, 50) # => ["c", "d"]
4251 * If <tt>start == a.size</tt> and +length+ is non-negative,
4252 * returns a new empty array.
4254 * If +length+ is negative, returns +nil+.
4256 * With Range argument +range+ given,
4257 * treats <tt>range.min</tt> as +start+ (as above)
4258 * and <tt>range.size</tt> as +length+ (as above):
4260 * a = ['a', 'b', 'c', 'd']
4261 * a.slice!(1..2) # => ["b", "c"]
4264 * If <tt>range.start == a.size</tt>, returns a new empty array:
4266 * a = ['a', 'b', 'c', 'd']
4267 * a.slice!(4..5) # => []
4269 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4271 * a = ['a', 'b', 'c', 'd']
4272 a.slice!(5..6) # => nil
4274 * If <tt>range.start</tt> is negative,
4275 * calculates the start index by counting backwards from the end of +self+:
4277 * a = ['a', 'b', 'c', 'd']
4278 * a.slice!(-2..2) # => ["c"]
4280 * If <tt>range.end</tt> is negative,
4281 * calculates the end index by counting backwards from the end of +self+:
4283 * a = ['a', 'b', 'c', 'd']
4284 * a.slice!(0..-2) # => ["a", "b", "c"]
4286 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4290 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4295 rb_ary_modify_check(ary
);
4296 rb_check_arity(argc
, 1, 2);
4300 pos
= NUM2LONG(argv
[0]);
4301 len
= NUM2LONG(argv
[1]);
4302 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4305 if (!FIXNUM_P(arg1
)) {
4306 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4309 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4319 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4323 ary_reject(VALUE orig
, VALUE result
)
4327 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4328 VALUE v
= RARRAY_AREF(orig
, i
);
4330 if (!RTEST(rb_yield(v
))) {
4331 rb_ary_push(result
, v
);
4338 reject_bang_i(VALUE a
)
4340 volatile struct select_bang_arg
*arg
= (void *)a
;
4341 VALUE ary
= arg
->ary
;
4344 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4345 VALUE v
= RARRAY_AREF(ary
, i1
);
4346 if (RTEST(rb_yield(v
))) continue;
4348 rb_ary_store(ary
, i2
, v
);
4352 return (i1
== i2
) ? Qnil
: ary
;
4356 ary_reject_bang(VALUE ary
)
4358 struct select_bang_arg args
;
4359 rb_ary_modify_check(ary
);
4361 args
.len
[0] = args
.len
[1] = 0;
4362 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4367 * reject! {|element| ... } -> self or nil
4368 * reject! -> new_enumerator
4370 * With a block given, calls the block with each element of +self+;
4371 * removes each element for which the block returns a truthy value.
4373 * Returns +self+ if any elements removed:
4375 * a = [:foo, 'bar', 2, 'bat']
4376 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4378 * Returns +nil+ if no elements removed.
4380 * With no block given, returns a new Enumerator.
4382 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4386 rb_ary_reject_bang(VALUE ary
)
4388 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4390 return ary_reject_bang(ary
);
4395 * reject {|element| ... } -> new_array
4396 * reject -> new_enumerator
4398 * With a block given, returns a new array whose elements are all those from +self+
4399 * for which the block returns +false+ or +nil+:
4401 * a = [:foo, 'bar', 2, 'bat']
4402 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4405 * With no block given, returns a new Enumerator.
4407 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4411 rb_ary_reject(VALUE ary
)
4415 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4416 rejected_ary
= rb_ary_new();
4417 ary_reject(ary
, rejected_ary
);
4418 return rejected_ary
;
4423 * delete_if {|element| ... } -> self
4424 * delete_if -> new_numerator
4426 * With a block given, calls the block with each element of +self+;
4427 * removes the element if the block returns a truthy value;
4430 * a = [:foo, 'bar', 2, 'bat']
4431 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4433 * With no block given, returns a new Enumerator.
4435 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4439 rb_ary_delete_if(VALUE ary
)
4442 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4443 ary_reject_bang(ary
);
4448 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4450 VALUE
*args
= (VALUE
*)cbarg
;
4451 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4452 rb_ary_push(args
[0], val
);
4453 if (--args
[1] == 0) rb_iter_break();
4458 take_items(VALUE obj
, long n
)
4460 VALUE result
= rb_check_array_type(obj
);
4463 if (n
== 0) return result
;
4464 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4465 result
= rb_ary_new2(n
);
4466 args
[0] = result
; args
[1] = (VALUE
)n
;
4467 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4468 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4476 * zip(*other_arrays) -> new_array
4477 * zip(*other_arrays) {|sub_array| ... } -> nil
4479 * With no block given, combines +self+ with the collection of +other_arrays+;
4480 * returns a new array of sub-arrays:
4482 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4483 * # => [[0, "zero", :zero], [1, "one", :one]]
4487 * - The outer array is of size <tt>self.size</tt>.
4488 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4489 * - The _nth_ sub-array contains (in order):
4491 * - The _nth_ element of +self+.
4492 * - The _nth_ element of each of the other arrays, as available.
4497 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4498 * # => [[0, "zero", :zero], [1, "one", :one]]
4499 * zipped.size # => 2 # Same size as a.
4500 * zipped.first.size # => 3 # Size of other arrays plus 1.
4502 * When the other arrays are all the same size as +self+,
4503 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4504 * (including +self+), with no omissions or additions:
4506 * a = [:a0, :a1, :a2, :a3]
4507 * b = [:b0, :b1, :b2, :b3]
4508 * c = [:c0, :c1, :c2, :c3]
4517 * When one of the other arrays is smaller than +self+,
4518 * pads the corresponding sub-array with +nil+ elements:
4520 * a = [:a0, :a1, :a2, :a3]
4521 * b = [:b0, :b1, :b2]
4531 * When one of the other arrays is larger than +self+,
4532 * _ignores_ its trailing elements:
4534 * a = [:a0, :a1, :a2, :a3]
4535 * b = [:b0, :b1, :b2, :b3, :b4]
4536 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4545 * With a block given, calls the block with each of the other arrays;
4549 * a = [:a0, :a1, :a2, :a3]
4550 * b = [:b0, :b1, :b2, :b3]
4551 * c = [:c0, :c1, :c2, :c3]
4552 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4560 * For an *object* in *other_arrays* that is not actually an array,
4561 * forms the the "other array" as <tt>object.to_ary</tt>, if defined,
4562 * or as <tt>object.each.to_a</tt> otherwise.
4564 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4568 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4571 long len
= RARRAY_LEN(ary
);
4572 VALUE result
= Qnil
;
4574 for (i
=0; i
<argc
; i
++) {
4575 argv
[i
] = take_items(argv
[i
], len
);
4578 if (rb_block_given_p()) {
4579 int arity
= rb_block_arity();
4584 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4586 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4587 tmp
[0] = RARRAY_AREF(ary
, i
);
4588 for (j
=0; j
<argc
; j
++) {
4589 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4591 rb_yield_values2(argc
+1, tmp
);
4594 if (work
) ALLOCV_END(work
);
4597 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4598 VALUE tmp
= rb_ary_new2(argc
+1);
4600 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4601 for (j
=0; j
<argc
; j
++) {
4602 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4609 result
= rb_ary_new_capa(len
);
4611 for (i
=0; i
<len
; i
++) {
4612 VALUE tmp
= rb_ary_new_capa(argc
+1);
4614 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4615 for (j
=0; j
<argc
; j
++) {
4616 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4618 rb_ary_push(result
, tmp
);
4627 * transpose -> new_array
4629 * Returns a new array that is +self+
4630 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4632 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4633 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4635 * The elements of +self+ must all be the same size.
4637 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4641 rb_ary_transpose(VALUE ary
)
4643 long elen
= -1, alen
, i
, j
;
4644 VALUE tmp
, result
= 0;
4646 alen
= RARRAY_LEN(ary
);
4647 if (alen
== 0) return rb_ary_dup(ary
);
4648 for (i
=0; i
<alen
; i
++) {
4649 tmp
= to_ary(rb_ary_elt(ary
, i
));
4650 if (elen
< 0) { /* first element */
4651 elen
= RARRAY_LEN(tmp
);
4652 result
= rb_ary_new2(elen
);
4653 for (j
=0; j
<elen
; j
++) {
4654 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4657 else if (elen
!= RARRAY_LEN(tmp
)) {
4658 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4659 RARRAY_LEN(tmp
), elen
);
4661 for (j
=0; j
<elen
; j
++) {
4662 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4670 * initialize_copy(other_array) -> self
4671 * replace(other_array) -> self
4673 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4674 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4677 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4678 * a.replace(['d', 'e']) # => ["d", "e"]
4680 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4684 rb_ary_replace(VALUE copy
, VALUE orig
)
4686 rb_ary_modify_check(copy
);
4687 orig
= to_ary(orig
);
4688 if (copy
== orig
) return copy
;
4692 /* orig has enough space to embed the contents of orig. */
4693 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4694 RUBY_ASSERT(ARY_EMBED_P(copy
));
4695 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4696 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4698 /* orig is embedded but copy does not have enough space to embed the
4699 * contents of orig. */
4700 else if (ARY_EMBED_P(orig
)) {
4701 long len
= ARY_EMBED_LEN(orig
);
4702 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4704 FL_UNSET_EMBED(copy
);
4705 ARY_SET_PTR(copy
, ptr
);
4706 ARY_SET_LEN(copy
, len
);
4707 ARY_SET_CAPA(copy
, len
);
4709 // No allocation and exception expected that could leave `copy` in a
4710 // bad state from the edits above.
4711 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4713 /* Otherwise, orig is on heap and copy does not have enough space to embed
4714 * the contents of orig. */
4716 VALUE shared_root
= ary_make_shared(orig
);
4717 FL_UNSET_EMBED(copy
);
4718 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4719 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4720 rb_ary_set_shared(copy
, shared_root
);
4730 * Removes all elements from +self+; returns +self+:
4732 * a = [:foo, 'bar', 2]
4735 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4739 rb_ary_clear(VALUE ary
)
4741 rb_ary_modify_check(ary
);
4742 if (ARY_SHARED_P(ary
)) {
4743 rb_ary_unshare(ary
);
4745 ARY_SET_EMBED_LEN(ary
, 0);
4748 ARY_SET_LEN(ary
, 0);
4749 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4750 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4759 * fill(object, start = nil, count = nil) -> new_array
4760 * fill(object, range) -> new_array
4761 * fill(start = nil, count = nil) {|element| ... } -> new_array
4762 * fill(range) {|element| ... } -> new_array
4764 * Replaces selected elements in +self+;
4765 * may add elements to +self+;
4766 * always returns +self+ (never a new array).
4770 * # Non-negative start.
4771 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4772 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4774 * # Extends with specified values if necessary.
4775 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4776 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4778 * # Fills with nils if necessary.
4779 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4780 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4782 * # For negative start, counts backwards from the end.
4783 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4784 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4787 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4788 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4790 * When arguments +start+ and +count+ are given,
4791 * they select the elements of +self+ to be replaced;
4793 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4796 * - +start+ specifies the zero-based offset of the first element to be replaced;
4798 * - +count+ is the number of consecutive elements to be replaced;
4799 * +nil+ means "all the rest."
4801 * With argument +object+ given,
4802 * that one object is used for all replacements:
4804 * o = Object.new # => #<Object:0x0000014e7bff7600>
4805 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4807 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4809 * With a block given, the block is called once for each element to be replaced;
4810 * the value passed to the block is the _index_ of the element to be replaced
4811 * (not the element itself);
4812 * the block's return value replaces the element:
4814 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4815 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4817 * For arguments +start+ and +count+:
4819 * - If +start+ is non-negative,
4820 * replaces +count+ elements beginning at offset +start+:
4822 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4823 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4824 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4826 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4827 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4828 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4830 * Extends +self+ if necessary:
4832 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4833 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4835 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4836 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4838 * Fills with +nil+ if necessary:
4840 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4841 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4843 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4844 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4846 * Does nothing if +count+ is non-positive:
4848 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4849 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4850 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4852 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4853 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4854 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4856 * - If +start+ is negative, counts backwards from the end of +self+:
4858 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4859 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4861 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4862 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4864 * Extends +self+ if necessary:
4866 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4867 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4869 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4870 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4872 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4874 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4875 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4877 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4878 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4880 * Does nothing if +count+ is non-positive:
4882 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4883 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4885 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4886 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4888 * When argument +range+ is given,
4889 * it must be a Range object whose members are numeric;
4890 * its +begin+ and +end+ values determine the elements of +self+
4893 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4896 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4897 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4899 * If +end+ is smaller than +begin+, replaces no elements:
4901 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4902 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4904 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4906 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4907 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4908 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4910 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4911 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4912 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4914 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4916 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4917 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4919 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4920 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4922 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4923 * replaces elements to the end of +self+:
4925 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4926 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4928 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4929 * replaces elements from the beginning of +self+:
4931 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4932 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4934 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4938 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4940 VALUE item
= Qundef
, arg1
, arg2
;
4941 long beg
= 0, end
= 0, len
= 0;
4943 if (rb_block_given_p()) {
4944 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4945 argc
+= 1; /* hackish */
4948 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4953 len
= RARRAY_LEN(ary
);
4956 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4961 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4963 beg
= RARRAY_LEN(ary
) + beg
;
4964 if (beg
< 0) beg
= 0;
4966 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4973 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4974 rb_raise(rb_eArgError
, "argument too big");
4977 if (RARRAY_LEN(ary
) < end
) {
4978 if (end
>= ARY_CAPA(ary
)) {
4979 ary_resize_capa(ary
, end
);
4981 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4982 ARY_SET_LEN(ary
, end
);
4985 if (UNDEF_P(item
)) {
4989 for (i
=beg
; i
<end
; i
++) {
4990 v
= rb_yield(LONG2NUM(i
));
4991 if (i
>=RARRAY_LEN(ary
)) break;
4996 ary_memfill(ary
, beg
, len
, item
);
5003 * self + other_array -> new_array
5005 * Returns a new array containing all elements of +self+
5006 * followed by all elements of +other_array+:
5008 * a = [0, 1] + [2, 3]
5009 * a # => [0, 1, 2, 3]
5011 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5015 rb_ary_plus(VALUE x
, VALUE y
)
5018 long len
, xlen
, ylen
;
5021 xlen
= RARRAY_LEN(x
);
5022 ylen
= RARRAY_LEN(y
);
5024 z
= rb_ary_new2(len
);
5026 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
5027 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
5028 ARY_SET_LEN(z
, len
);
5033 ary_append(VALUE x
, VALUE y
)
5035 long n
= RARRAY_LEN(y
);
5037 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
5045 * concat(*other_arrays) -> self
5047 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5050 * a.concat(['two', 'three'], [:four, :five], a)
5051 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5053 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5057 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
5059 rb_ary_modify_check(ary
);
5062 rb_ary_concat(ary
, argv
[0]);
5064 else if (argc
> 1) {
5066 VALUE args
= rb_ary_hidden_new(argc
);
5067 for (i
= 0; i
< argc
; i
++) {
5068 rb_ary_concat(args
, argv
[i
]);
5070 ary_append(ary
, args
);
5078 rb_ary_concat(VALUE x
, VALUE y
)
5080 return ary_append(x
, to_ary(y
));
5085 * self * n -> new_array
5086 * self * string_separator -> new_string
5088 * When non-negative integer argument +n+ is given,
5089 * returns a new array built by concatenating +n+ copies of +self+:
5092 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5094 * When string argument +string_separator+ is given,
5095 * equivalent to <tt>self.join(string_separator)</tt>:
5097 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5102 rb_ary_times(VALUE ary
, VALUE times
)
5108 tmp
= rb_check_string_type(times
);
5110 return rb_ary_join(ary
, tmp
);
5113 len
= NUM2LONG(times
);
5115 ary2
= ary_new(rb_cArray
, 0);
5119 rb_raise(rb_eArgError
, "negative argument");
5121 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
5122 rb_raise(rb_eArgError
, "argument too big");
5124 len
*= RARRAY_LEN(ary
);
5126 ary2
= ary_new(rb_cArray
, len
);
5127 ARY_SET_LEN(ary2
, len
);
5129 ptr
= RARRAY_CONST_PTR(ary
);
5130 t
= RARRAY_LEN(ary
);
5132 ary_memcpy(ary2
, 0, t
, ptr
);
5133 while (t
<= len
/2) {
5134 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5138 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5147 * assoc(object) -> found_array or nil
5149 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5150 * and <tt>ele[0] == object</tt>:
5152 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5153 * a.assoc(4) # => [4, 5, 6]
5155 * Returns +nil+ if no such element is found.
5157 * Related: Array#rassoc;
5158 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5162 rb_ary_assoc(VALUE ary
, VALUE key
)
5167 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5168 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5169 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5170 rb_equal(RARRAY_AREF(v
, 0), key
))
5178 * rassoc(object) -> found_array or nil
5180 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5181 * and <tt>ele[1] == object</tt>:
5183 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5184 * a.rassoc(4) # => [2, 4]
5185 * a.rassoc(5) # => [4, 5, 6]
5187 * Returns +nil+ if no such element is found.
5189 * Related: Array#assoc;
5190 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5194 rb_ary_rassoc(VALUE ary
, VALUE value
)
5199 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5200 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5201 if (RB_TYPE_P(v
, T_ARRAY
) &&
5202 RARRAY_LEN(v
) > 1 &&
5203 rb_equal(RARRAY_AREF(v
, 1), value
))
5210 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5213 const VALUE
*p1
, *p2
;
5215 if (recur
) return Qtrue
; /* Subtle! */
5217 /* rb_equal() can evacuate ptrs */
5218 p1
= RARRAY_CONST_PTR(ary1
);
5219 p2
= RARRAY_CONST_PTR(ary2
);
5220 len1
= RARRAY_LEN(ary1
);
5222 for (i
= 0; i
< len1
; i
++) {
5224 if (rb_equal(*p1
, *p2
)) {
5225 len1
= RARRAY_LEN(ary1
);
5226 if (len1
!= RARRAY_LEN(ary2
))
5230 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5231 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5245 * self == other_array -> true or false
5247 * Returns whether both:
5249 * - +self+ and +other_array+ are the same size.
5250 * - Their corresponding elements are the same;
5251 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5252 * <tt>self[i] == other_array[i]</tt>.
5256 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5257 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5258 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5259 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5261 * This method is different from method Array#eql?,
5262 * which compares elements using <tt>Object#eql?</tt>.
5264 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5268 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5270 if (ary1
== ary2
) return Qtrue
;
5271 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5272 if (!rb_respond_to(ary2
, idTo_ary
)) {
5275 return rb_equal(ary2
, ary1
);
5277 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5278 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5279 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5283 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5287 if (recur
) return Qtrue
; /* Subtle! */
5288 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5289 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5297 * eql?(other_array) -> true or false
5299 * Returns +true+ if +self+ and +other_array+ are the same size,
5300 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5302 * a0 = [:foo, 'bar', 2]
5303 * a1 = [:foo, 'bar', 2]
5304 * a1.eql?(a0) # => true
5306 * Otherwise, returns +false+.
5308 * This method is different from method Array#==,
5309 * which compares using method <tt>Object#==</tt>.
5311 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5315 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5317 if (ary1
== ary2
) return Qtrue
;
5318 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5319 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5320 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5321 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5325 rb_ary_hash_values(long len
, const VALUE
*elements
)
5331 h
= rb_hash_start(len
);
5332 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5333 for (i
=0; i
<len
; i
++) {
5334 n
= rb_hash(elements
[i
]);
5335 h
= rb_hash_uint(h
, NUM2LONG(n
));
5345 * Returns the integer hash value for +self+.
5347 * Two arrays with the same content will have the same hash value
5348 * (and will compare using eql?):
5350 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5351 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5352 * ['a', 'b'].hash == ['a'].hash # => false
5357 rb_ary_hash(VALUE ary
)
5359 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5364 * include?(object) -> true or false
5366 * Returns whether for some element +element+ in +self+,
5367 * <tt>object == element</tt>:
5369 * [0, 1, 2].include?(2) # => true
5370 * [0, 1, 2].include?(2.0) # => true
5371 * [0, 1, 2].include?(2.1) # => false
5373 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5377 rb_ary_includes(VALUE ary
, VALUE item
)
5382 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5383 e
= RARRAY_AREF(ary
, i
);
5384 if (rb_equal(e
, item
)) {
5392 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5397 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5398 e
= RARRAY_AREF(ary
, i
);
5399 if (rb_eql(item
, e
)) {
5407 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5411 if (recur
) return Qundef
; /* Subtle! */
5412 len
= RARRAY_LEN(ary1
);
5413 if (len
> RARRAY_LEN(ary2
)) {
5414 len
= RARRAY_LEN(ary2
);
5416 for (i
=0; i
<len
; i
++) {
5417 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5418 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5419 if (v
!= INT2FIX(0)) {
5428 * self <=> other_array -> -1, 0, or 1
5430 * Returns -1, 0, or 1 as +self+ is determined
5431 * to be less than, equal to, or greater than +other_array+.
5433 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5435 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5436 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5438 * [0, 1, 2] <=> [0, 0, 2] # => 1
5440 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5442 * [0, 1, 2] <=> [0, 2, 2] # => -1
5444 * - Continues if <tt>result[i]</tt> is 0.
5446 * When every +result+ is 0,
5447 * returns <tt>self.size <=> other_array.size</tt>
5448 * (see Integer#<=>):
5450 * [0, 1, 2] <=> [0, 1] # => 1
5451 * [0, 1, 2] <=> [0, 1, 2] # => 0
5452 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5454 * Note that when +other_array+ is larger than +self+,
5455 * its trailing elements do not affect the result:
5457 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5458 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5459 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5461 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5465 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5470 ary2
= rb_check_array_type(ary2
);
5471 if (NIL_P(ary2
)) return Qnil
;
5472 if (ary1
== ary2
) return INT2FIX(0);
5473 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5474 if (!UNDEF_P(v
)) return v
;
5475 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5476 if (len
== 0) return INT2FIX(0);
5477 if (len
> 0) return INT2FIX(1);
5482 ary_add_hash(VALUE hash
, VALUE ary
)
5486 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5487 VALUE elt
= RARRAY_AREF(ary
, i
);
5488 rb_hash_add_new_element(hash
, elt
, elt
);
5494 ary_tmp_hash_new(VALUE ary
)
5496 long size
= RARRAY_LEN(ary
);
5497 VALUE hash
= rb_hash_new_with_size(size
);
5499 RBASIC_CLEAR_CLASS(hash
);
5504 ary_make_hash(VALUE ary
)
5506 VALUE hash
= ary_tmp_hash_new(ary
);
5507 return ary_add_hash(hash
, ary
);
5511 ary_add_hash_by(VALUE hash
, VALUE ary
)
5515 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5516 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5517 rb_hash_add_new_element(hash
, k
, v
);
5523 ary_make_hash_by(VALUE ary
)
5525 VALUE hash
= ary_tmp_hash_new(ary
);
5526 return ary_add_hash_by(hash
, ary
);
5531 * self - other_array -> new_array
5533 * Returns a new array containing only those elements of +self+
5534 * that are not found in +other_array+;
5535 * the order from +self+ is preserved:
5537 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5538 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5539 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5541 * Element are compared using method <tt>#eql?</tt>
5542 * (as defined in each element of +self+).
5544 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5548 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5554 ary2
= to_ary(ary2
);
5555 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5556 ary3
= rb_ary_new();
5558 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5559 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5560 VALUE elt
= rb_ary_elt(ary1
, i
);
5561 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5562 rb_ary_push(ary3
, elt
);
5567 hash
= ary_make_hash(ary2
);
5568 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5569 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5570 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5578 * difference(*other_arrays = []) -> new_array
5580 * Returns a new array containing only those elements from +self+
5581 * that are not found in any of the given +other_arrays+;
5582 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5584 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5585 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5586 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5587 * [0, 1, 2].difference # => [0, 1, 2]
5589 * Returns a copy of +self+ if no arguments are given.
5592 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5596 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5601 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5602 ary_diff
= rb_ary_new();
5603 length
= RARRAY_LEN(ary
);
5605 for (i
= 0; i
< argc
; i
++) {
5606 argv
[i
] = to_ary(argv
[i
]);
5607 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5608 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5611 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5613 VALUE elt
= rb_ary_elt(ary
, i
);
5614 for (j
= 0; j
< argc
; j
++) {
5616 if (rb_hash_stlike_lookup(argv
[j
], elt
, NULL
))
5620 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5623 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5634 * self & other_array -> new_array
5636 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5637 * that is, containing those elements found in both +self+ and +other_array+:
5639 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5643 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5645 * Preserves order from +self+:
5647 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5649 * Identifies common elements using method <tt>#eql?</tt>
5650 * (as defined in each element of +self+).
5652 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5657 rb_ary_and(VALUE ary1
, VALUE ary2
)
5659 VALUE hash
, ary3
, v
;
5663 ary2
= to_ary(ary2
);
5664 ary3
= rb_ary_new();
5665 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5667 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5668 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5669 v
= RARRAY_AREF(ary1
, i
);
5670 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5671 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5672 rb_ary_push(ary3
, v
);
5677 hash
= ary_make_hash(ary2
);
5679 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5680 v
= RARRAY_AREF(ary1
, i
);
5682 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5683 rb_ary_push(ary3
, v
);
5692 * intersection(*other_arrays) -> new_array
5694 * Returns a new array containing each element in +self+ that is +#eql?+
5695 * to at least one element in each of the given +other_arrays+;
5696 * duplicates are omitted:
5698 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5700 * Each element must correctly implement method <tt>#hash</tt>.
5702 * Order from +self+ is preserved:
5704 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5706 * Returns a copy of +self+ if no arguments are given.
5708 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5712 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5714 VALUE result
= rb_ary_dup(ary
);
5717 for (i
= 0; i
< argc
; i
++) {
5718 result
= rb_ary_and(result
, argv
[i
]);
5725 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5727 if (existing
) return ST_STOP
;
5728 *key
= *value
= (VALUE
)arg
;
5733 rb_ary_union(VALUE ary_union
, VALUE ary
)
5736 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5737 VALUE elt
= rb_ary_elt(ary
, i
);
5738 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5739 rb_ary_push(ary_union
, elt
);
5744 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5747 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5748 VALUE elt
= RARRAY_AREF(ary2
, i
);
5749 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5750 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5757 * self | other_array -> new_array
5759 * Returns the union of +self+ and +other_array+;
5760 * duplicates are removed; order is preserved;
5761 * items are compared using <tt>eql?</tt>:
5763 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5764 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5765 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5767 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5771 rb_ary_or(VALUE ary1
, VALUE ary2
)
5775 ary2
= to_ary(ary2
);
5776 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5777 VALUE ary3
= rb_ary_new();
5778 rb_ary_union(ary3
, ary1
);
5779 rb_ary_union(ary3
, ary2
);
5783 hash
= ary_make_hash(ary1
);
5784 rb_ary_union_hash(hash
, ary2
);
5786 return rb_hash_values(hash
);
5791 * union(*other_arrays) -> new_array
5793 * Returns a new array that is the union of the elements of +self+
5794 * and all given arrays +other_arrays+;
5795 * items are compared using <tt>eql?</tt>:
5797 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5799 * Removes duplicates (preserving the first found):
5801 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5803 * Preserves order (preserving the position of the first found):
5805 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5807 * With no arguments given, returns a copy of +self+.
5809 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5813 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5819 sum
= RARRAY_LEN(ary
);
5820 for (i
= 0; i
< argc
; i
++) {
5821 argv
[i
] = to_ary(argv
[i
]);
5822 sum
+= RARRAY_LEN(argv
[i
]);
5825 if (sum
<= SMALL_ARRAY_LEN
) {
5826 VALUE ary_union
= rb_ary_new();
5828 rb_ary_union(ary_union
, ary
);
5829 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5834 hash
= ary_make_hash(ary
);
5835 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5837 return rb_hash_values(hash
);
5842 * intersect?(other_array) -> true or false
5844 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5846 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5847 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5849 * Each element must correctly implement method <tt>#hash</tt>.
5851 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5855 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5857 VALUE hash
, v
, result
, shorter
, longer
;
5861 ary2
= to_ary(ary2
);
5862 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5864 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5865 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5866 v
= RARRAY_AREF(ary1
, i
);
5867 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5874 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5879 hash
= ary_make_hash(shorter
);
5882 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5883 v
= RARRAY_AREF(longer
, i
);
5885 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5895 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5897 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5900 for (; i
< RARRAY_LEN(ary
); ++i
) {
5901 v
= RARRAY_AREF(ary
, i
);
5903 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5912 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5914 const long n
= RARRAY_LEN(ary
);
5915 RUBY_ASSERT(i
> 0 && i
< n
);
5916 RUBY_ASSERT(FIXNUM_P(vmax
));
5919 for (; i
< n
; ++i
) {
5920 v
= RARRAY_AREF(ary
, i
);
5923 if ((long)vmax
< (long)v
) {
5928 return ary_max_generic(ary
, i
, vmax
);
5936 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5938 const long n
= RARRAY_LEN(ary
);
5939 RUBY_ASSERT(i
> 0 && i
< n
);
5940 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5943 for (; i
< n
; ++i
) {
5944 v
= RARRAY_AREF(ary
, i
);
5946 if (RB_FLOAT_TYPE_P(v
)) {
5947 if (rb_float_cmp(vmax
, v
) < 0) {
5952 return ary_max_generic(ary
, i
, vmax
);
5960 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5962 const long n
= RARRAY_LEN(ary
);
5963 RUBY_ASSERT(i
> 0 && i
< n
);
5964 RUBY_ASSERT(STRING_P(vmax
));
5967 for (; i
< n
; ++i
) {
5968 v
= RARRAY_AREF(ary
, i
);
5971 if (rb_str_cmp(vmax
, v
) < 0) {
5976 return ary_max_generic(ary
, i
, vmax
);
5986 * max(count) -> new_array
5987 * max {|a, b| ... } -> element
5988 * max(count) {|a, b| ... } -> new_array
5990 * Returns one of the following:
5992 * - The maximum-valued element from +self+.
5993 * - A new array of maximum-valued elements from +self+.
5995 * Does not modify +self+.
5997 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6000 * With no argument and no block, returns the element in +self+
6001 * having the maximum value per method <tt>#<=></tt>:
6003 * [1, 0, 3, 2].max # => 3
6005 * With non-negative numeric argument +count+ and no block,
6006 * returns a new array with at most +count+ elements,
6007 * in descending order, per method <tt>#<=></tt>:
6009 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6010 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6011 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6012 * [1, 0, 3, 2].max(0) # => []
6014 * With a block given, the block must return a numeric.
6016 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6017 * returns the element having the maximum value per the block:
6019 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6022 * With non-negative numeric argument +count+ and a block,
6023 * returns a new array with at most +count+ elements,
6024 * in descending order, per the block:
6026 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6027 * # => ["000", "00"]
6029 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6032 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
6034 VALUE result
= Qundef
, v
;
6038 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6039 return rb_nmin_run(ary
, num
, 0, 1, 1);
6041 const long n
= RARRAY_LEN(ary
);
6042 if (rb_block_given_p()) {
6043 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6044 v
= RARRAY_AREF(ary
, i
);
6045 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
6051 result
= RARRAY_AREF(ary
, 0);
6053 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6054 return ary_max_opt_fixnum(ary
, 1, result
);
6056 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6057 return ary_max_opt_string(ary
, 1, result
);
6059 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6060 return ary_max_opt_float(ary
, 1, result
);
6063 return ary_max_generic(ary
, 1, result
);
6067 if (UNDEF_P(result
)) return Qnil
;
6072 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
6074 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
6077 for (; i
< RARRAY_LEN(ary
); ++i
) {
6078 v
= RARRAY_AREF(ary
, i
);
6080 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
6089 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
6091 const long n
= RARRAY_LEN(ary
);
6092 RUBY_ASSERT(i
> 0 && i
< n
);
6093 RUBY_ASSERT(FIXNUM_P(vmin
));
6096 for (; i
< n
; ++i
) {
6097 a
= RARRAY_AREF(ary
, i
);
6100 if ((long)vmin
> (long)a
) {
6105 return ary_min_generic(ary
, i
, vmin
);
6113 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
6115 const long n
= RARRAY_LEN(ary
);
6116 RUBY_ASSERT(i
> 0 && i
< n
);
6117 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
6120 for (; i
< n
; ++i
) {
6121 a
= RARRAY_AREF(ary
, i
);
6123 if (RB_FLOAT_TYPE_P(a
)) {
6124 if (rb_float_cmp(vmin
, a
) > 0) {
6129 return ary_min_generic(ary
, i
, vmin
);
6137 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
6139 const long n
= RARRAY_LEN(ary
);
6140 RUBY_ASSERT(i
> 0 && i
< n
);
6141 RUBY_ASSERT(STRING_P(vmin
));
6144 for (; i
< n
; ++i
) {
6145 a
= RARRAY_AREF(ary
, i
);
6148 if (rb_str_cmp(vmin
, a
) > 0) {
6153 return ary_min_generic(ary
, i
, vmin
);
6163 * min(count) -> new_array
6164 * min {|a, b| ... } -> element
6165 * min(count) {|a, b| ... } -> new_array
6167 * Returns one of the following:
6169 * - The minimum-valued element from +self+.
6170 * - A new array of minimum-valued elements from +self+.
6172 * Does not modify +self+.
6174 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6177 * With no argument and no block, returns the element in +self+
6178 * having the minimum value per method <tt>#<=></tt>:
6180 * [1, 0, 3, 2].min # => 0
6182 * With non-negative numeric argument +count+ and no block,
6183 * returns a new array with at most +count+ elements,
6184 * in ascending order, per method <tt>#<=></tt>:
6186 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6187 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6188 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6189 * [1, 0, 3, 2].min(0) # => []
6191 * With a block given, the block must return a numeric.
6193 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6194 * returns the element having the minimum value per the block:
6196 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6199 * With non-negative numeric argument +count+ and a block,
6200 * returns a new array with at most +count+ elements,
6201 * in ascending order, per the block:
6203 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6206 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6209 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6211 VALUE result
= Qundef
, v
;
6215 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6216 return rb_nmin_run(ary
, num
, 0, 0, 1);
6218 const long n
= RARRAY_LEN(ary
);
6219 if (rb_block_given_p()) {
6220 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6221 v
= RARRAY_AREF(ary
, i
);
6222 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6228 result
= RARRAY_AREF(ary
, 0);
6230 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6231 return ary_min_opt_fixnum(ary
, 1, result
);
6233 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6234 return ary_min_opt_string(ary
, 1, result
);
6236 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6237 return ary_min_opt_float(ary
, 1, result
);
6240 return ary_min_generic(ary
, 1, result
);
6244 if (UNDEF_P(result
)) return Qnil
;
6251 * minmax {|a, b| ... } -> array
6253 * Returns a 2-element array containing the minimum-valued and maximum-valued
6254 * elements from +self+;
6255 * does not modify +self+.
6257 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6259 * [1, 0, 3, 2].minmax # => [0, 3]
6261 * With a block given, the block must return a numeric;
6262 * the block is called <tt>self.size - 1</tt> times to compare elements;
6263 * returns the elements having the minimum and maximum values per the block:
6265 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6268 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6271 rb_ary_minmax(VALUE ary
)
6273 if (rb_block_given_p()) {
6274 return rb_call_super(0, NULL
);
6276 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6280 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6282 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6288 * uniq! -> self or nil
6289 * uniq! {|element| ... } -> self or nil
6291 * Removes duplicate elements from +self+, the first occurrence always being retained;
6292 * returns +self+ if any elements removed, +nil+ otherwise.
6294 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6295 * to compare elements:
6297 * a = [0, 0, 1, 1, 2, 2]
6298 * a.uniq! # => [0, 1, 2]
6301 * With a block given, calls the block for each element;
6302 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6303 * to compare <i>block return values</i>;
6304 * that is, an element is a duplicate if its block return value
6305 * is the same as that of a previous element:
6307 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6308 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6309 * a.uniq! {|element| element.size } # => nil
6311 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6314 rb_ary_uniq_bang(VALUE ary
)
6319 rb_ary_modify_check(ary
);
6320 if (RARRAY_LEN(ary
) <= 1)
6322 if (rb_block_given_p())
6323 hash
= ary_make_hash_by(ary
);
6325 hash
= ary_make_hash(ary
);
6327 hash_size
= RHASH_SIZE(hash
);
6328 if (RARRAY_LEN(ary
) == hash_size
) {
6331 rb_ary_modify_check(ary
);
6332 ARY_SET_LEN(ary
, 0);
6333 if (ARY_SHARED_P(ary
)) {
6334 rb_ary_unshare(ary
);
6337 ary_resize_capa(ary
, hash_size
);
6338 rb_hash_foreach(hash
, push_value
, ary
);
6346 * uniq {|element| ... } -> new_array
6348 * Returns a new array containing those elements from +self+ that are not duplicates,
6349 * the first occurrence always being retained.
6351 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6352 * to compare elements:
6354 * a = [0, 0, 1, 1, 2, 2]
6355 * a.uniq # => [0, 1, 2]
6357 * With a block given, calls the block for each element;
6358 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6359 * to compare <i>block return values</i>;
6360 * that is, an element is a duplicate if its block return value
6361 * is the same as that of a previous element:
6363 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6364 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6366 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6370 rb_ary_uniq(VALUE ary
)
6374 if (RARRAY_LEN(ary
) <= 1) {
6376 uniq
= rb_ary_dup(ary
);
6378 else if (rb_block_given_p()) {
6379 hash
= ary_make_hash_by(ary
);
6380 uniq
= rb_hash_values(hash
);
6383 hash
= ary_make_hash(ary
);
6384 uniq
= rb_hash_values(hash
);
6392 * compact! -> self or nil
6394 * Removes all +nil+ elements from +self+;
6395 * Returns +self+ if any elements are removed, +nil+ otherwise:
6397 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6398 * a.compact! # => [0, false, "", [], {}]
6399 * a # => [0, false, "", [], {}]
6400 * a.compact! # => nil
6402 * Related: Array#compact;
6403 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6407 rb_ary_compact_bang(VALUE ary
)
6413 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6414 end
= p
+ RARRAY_LEN(ary
);
6420 n
= p
- RARRAY_CONST_PTR(ary
);
6421 if (RARRAY_LEN(ary
) == n
) {
6424 ary_resize_smaller(ary
, n
);
6431 * compact -> new_array
6433 * Returns a new array containing only the non-+nil+ elements from +self+;
6434 * element order is preserved:
6436 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6437 * a.compact # => [0, false, "", [], {}]
6439 * Related: Array#compact!;
6440 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6444 rb_ary_compact(VALUE ary
)
6446 ary
= rb_ary_dup(ary
);
6447 rb_ary_compact_bang(ary
);
6454 * count(object) -> integer
6455 * count {|element| ... } -> integer
6457 * Returns a count of specified elements.
6459 * With no argument and no block, returns the count of all elements:
6461 * [0, :one, 'two', 3, 3.0].count # => 5
6463 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6465 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6467 * With no argument and a block given, calls the block with each element;
6468 * returns the count of elements for which the block returns a truthy value:
6470 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6472 * With argument +object+ and a block given, issues a warning, ignores the block,
6473 * and returns the count of elements <tt>==</tt> to +object+.
6475 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6479 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6483 if (rb_check_arity(argc
, 0, 1) == 0) {
6486 if (!rb_block_given_p())
6487 return LONG2NUM(RARRAY_LEN(ary
));
6489 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6490 v
= RARRAY_AREF(ary
, i
);
6491 if (RTEST(rb_yield(v
))) n
++;
6495 VALUE obj
= argv
[0];
6497 if (rb_block_given_p()) {
6498 rb_warn("given block not used");
6500 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6501 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6509 flatten(VALUE ary
, int level
)
6512 VALUE stack
, result
, tmp
= 0, elt
;
6513 VALUE memo
= Qfalse
;
6515 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6516 elt
= RARRAY_AREF(ary
, i
);
6517 tmp
= rb_check_array_type(elt
);
6522 if (i
== RARRAY_LEN(ary
)) {
6526 result
= ary_new(0, RARRAY_LEN(ary
));
6527 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6528 ARY_SET_LEN(result
, i
);
6530 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6531 rb_ary_push(stack
, ary
);
6532 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6535 memo
= rb_obj_hide(rb_ident_hash_new());
6536 rb_hash_aset(memo
, ary
, Qtrue
);
6537 rb_hash_aset(memo
, tmp
, Qtrue
);
6544 while (i
< RARRAY_LEN(ary
)) {
6545 elt
= RARRAY_AREF(ary
, i
++);
6546 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6547 rb_ary_push(result
, elt
);
6550 tmp
= rb_check_array_type(elt
);
6551 if (RBASIC(result
)->klass
) {
6553 rb_hash_clear(memo
);
6555 rb_raise(rb_eRuntimeError
, "flatten reentered");
6558 rb_ary_push(result
, elt
);
6562 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6563 rb_hash_clear(memo
);
6564 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6566 rb_hash_aset(memo
, tmp
, Qtrue
);
6568 rb_ary_push(stack
, ary
);
6569 rb_ary_push(stack
, LONG2NUM(i
));
6574 if (RARRAY_LEN(stack
) == 0) {
6578 rb_hash_delete(memo
, ary
);
6580 tmp
= rb_ary_pop(stack
);
6582 ary
= rb_ary_pop(stack
);
6586 rb_hash_clear(memo
);
6589 RBASIC_SET_CLASS(result
, rb_cArray
);
6595 * flatten!(depth = nil) -> self or nil
6597 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6598 * +depth+ must be an
6599 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6601 * At each level of recursion:
6603 * - Each element that is an array is "flattened"
6604 * (that is, replaced by its individual array elements).
6605 * - Each element that is not an array is unchanged
6606 * (even if the element is an object that has instance method +flatten+).
6608 * Returns +nil+ if no elements were flattened.
6610 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6612 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6613 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6614 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6615 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6616 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6617 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6619 * With +nil+ or negative argument +depth+, flattens all levels:
6621 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6622 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6624 * Related: Array#flatten;
6625 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6629 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6631 int mod
= 0, level
= -1;
6634 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6635 rb_ary_modify_check(ary
);
6636 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6637 if (level
== 0) return Qnil
;
6639 result
= flatten(ary
, level
);
6640 if (result
== ary
) {
6643 if (!(mod
= ARY_EMBED_P(result
))) rb_ary_freeze(result
);
6644 rb_ary_replace(ary
, result
);
6645 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6652 * flatten(depth = nil) -> new_array
6654 * Returns a new array that is a recursive flattening of +self+
6655 * to +depth+ levels of recursion;
6656 * +depth+ must be an
6657 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6659 * At each level of recursion:
6661 * - Each element that is an array is "flattened"
6662 * (that is, replaced by its individual array elements).
6663 * - Each element that is not an array is unchanged
6664 * (even if the element is an object that has instance method +flatten+).
6666 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6668 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6669 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6670 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6671 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6672 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6673 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6674 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6676 * With +nil+ or negative +depth+, flattens all levels.
6678 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6679 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6681 * Related: Array#flatten!;
6682 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6686 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6691 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6692 level
= NUM2INT(argv
[0]);
6693 if (level
== 0) return ary_make_shared_copy(ary
);
6696 result
= flatten(ary
, level
);
6697 if (result
== ary
) {
6698 result
= ary_make_shared_copy(ary
);
6704 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6707 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6712 i
= len
= RARRAY_LEN(ary
);
6713 RARRAY_PTR_USE(ary
, ptr
, {
6715 long j
= RAND_UPTO(i
);
6717 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6718 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6724 }); /* WB: no new reference */
6729 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6731 ary
= rb_ary_dup(ary
);
6732 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6736 static const rb_data_type_t ary_sample_memo_type
= {
6737 .wrap_struct_name
= "ary_sample_memo",
6739 .dfree
= (RUBY_DATA_FUNC
)st_free_table
,
6741 .flags
= RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_FREE_IMMEDIATELY
6745 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6748 long n
, len
, i
, j
, k
, idx
[10];
6749 long rnds
[numberof(idx
)];
6750 long memo_threshold
;
6752 len
= RARRAY_LEN(ary
);
6759 return rb_ary_elt(ary
, i
);
6762 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6763 if (n
> len
) n
= len
;
6764 if (n
<= numberof(idx
)) {
6765 for (i
= 0; i
< n
; ++i
) {
6766 rnds
[i
] = RAND_UPTO(len
- i
);
6770 len
= RARRAY_LEN(ary
);
6771 if (len
< k
&& n
<= numberof(idx
)) {
6772 for (i
= 0; i
< n
; ++i
) {
6773 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6776 if (n
> len
) n
= len
;
6779 return rb_ary_new_capa(0);
6782 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6787 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6794 if (j
>= i
) l
= i
, g
= ++j
;
6795 if (k
>= l
&& (++k
>= g
)) ++k
;
6797 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6800 len
< 2560 ? len
/ 128 :
6801 len
< 5120 ? len
/ 64 :
6802 len
< 10240 ? len
/ 32 :
6804 if (n
<= numberof(idx
)) {
6805 long sorted
[numberof(idx
)];
6806 sorted
[0] = idx
[0] = rnds
[0];
6807 for (i
=1; i
<n
; i
++) {
6809 for (j
= 0; j
< i
; ++j
) {
6810 if (k
< sorted
[j
]) break;
6813 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6814 sorted
[j
] = idx
[i
] = k
;
6816 result
= rb_ary_new_capa(n
);
6817 RARRAY_PTR_USE(result
, ptr_result
, {
6818 for (i
=0; i
<n
; i
++) {
6819 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6823 else if (n
<= memo_threshold
/ 2) {
6825 VALUE vmemo
= TypedData_Wrap_Struct(0, &ary_sample_memo_type
, 0);
6826 st_table
*memo
= st_init_numtable_with_size(n
);
6827 RTYPEDDATA_DATA(vmemo
) = memo
;
6828 result
= rb_ary_new_capa(n
);
6829 RARRAY_PTR_USE(result
, ptr_result
, {
6830 for (i
=0; i
<n
; i
++) {
6831 long r
= RAND_UPTO(len
-i
) + i
;
6833 if (r
> max_idx
) max_idx
= r
;
6835 len
= RARRAY_LEN(ary
);
6836 if (len
<= max_idx
) n
= 0;
6837 else if (n
> len
) n
= len
;
6838 RARRAY_PTR_USE(ary
, ptr_ary
, {
6839 for (i
=0; i
<n
; i
++) {
6840 long j2
= j
= ptr_result
[i
];
6843 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6844 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6845 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6846 ptr_result
[i
] = ptr_ary
[j2
];
6850 RTYPEDDATA_DATA(vmemo
) = 0;
6851 st_free_table(memo
);
6855 result
= rb_ary_dup(ary
);
6856 RBASIC_CLEAR_CLASS(result
);
6858 RARRAY_PTR_USE(result
, ptr_result
, {
6859 for (i
=0; i
<n
; i
++) {
6860 j
= RAND_UPTO(len
-i
) + i
;
6862 ptr_result
[j
] = ptr_result
[i
];
6866 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6868 ARY_SET_LEN(result
, n
);
6874 ary_sized_alloc(rb_execution_context_t
*ec
, VALUE self
)
6876 return rb_ary_new2(RARRAY_LEN(self
));
6880 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6882 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6886 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6890 if (args
&& (RARRAY_LEN(args
) > 0)) {
6891 n
= RARRAY_AREF(args
, 0);
6893 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6894 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6896 if (mul
<= 0) return INT2FIX(0);
6898 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6903 * cycle(count = nil) {|element| ... } -> nil
6904 * cycle(count = nil) -> new_enumerator
6906 * With a block given, may call the block, depending on the value of argument +count+;
6907 * +count+ must be an
6908 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6911 * When +count+ is positive,
6912 * calls the block with each element, then does so repeatedly,
6913 * until it has done so +count+ times; returns +nil+:
6916 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6917 * output # => [0, 1, 0, 1]
6919 * When +count+ is zero or negative, does not call the block:
6921 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6922 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6924 * When +count+ is +nil+, cycles forever:
6926 * # Prints 0 and 1 forever.
6927 * [0, 1].cycle {|element| puts element }
6928 * [0, 1].cycle(nil) {|element| puts element }
6930 * With no block given, returns a new Enumerator.
6932 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6935 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6939 rb_check_arity(argc
, 0, 1);
6941 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6942 if (argc
== 0 || NIL_P(argv
[0])) {
6946 n
= NUM2LONG(argv
[0]);
6947 if (n
<= 0) return Qnil
;
6950 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6951 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6952 rb_yield(RARRAY_AREF(ary
, i
));
6959 * Build a ruby array of the corresponding values and yield it to the
6961 * Return the class of +values+ for reentry check.
6964 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6966 const VALUE result
= rb_ary_new2(r
);
6969 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6970 ARY_SET_LEN(result
, r
);
6972 return !RBASIC(values
)->klass
;
6976 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6978 * When we have a complete permutation of array indices, copy the values
6979 * at those indices into a new array and yield that array.
6981 * n: the size of the set
6982 * r: the number of elements in each permutation
6983 * p: the array (of size r) that we're filling in
6984 * used: an array of booleans: whether a given index is already used
6985 * values: the Ruby array that holds the actual values to permute
6988 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6990 long i
= 0, index
= 0;
6993 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6996 i
= p
[--index
]; /* pop index */
6997 used
[i
++] = 0; /* index unused */
7002 used
[i
] = 1; /* mark index used */
7004 if (index
< r
-1) { /* if not done yet */
7008 for (i
= 0; i
< n
; ++i
) {
7009 if (used
[i
]) continue;
7011 if (!yield_indexed_values(values
, r
, p
)) {
7012 rb_raise(rb_eRuntimeError
, "permute reentered");
7015 i
= p
[--index
]; /* pop index */
7016 used
[i
] = 0; /* index unused */
7023 * Returns the product of from, from-1, ..., from - how_many + 1.
7024 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7027 descending_factorial(long from
, long how_many
)
7031 cnt
= LONG2FIX(from
);
7032 while (--how_many
> 0) {
7034 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
7038 cnt
= LONG2FIX(how_many
== 0);
7044 binomial_coefficient(long comb
, long size
)
7048 if (comb
> size
-comb
) {
7054 else if (comb
== 0) {
7058 for (i
= 1; i
< comb
; ++i
) {
7059 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
7060 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
7066 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7068 long n
= RARRAY_LEN(ary
);
7069 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
7071 return descending_factorial(n
, k
);
7076 * permutation(count = self.size) {|permutation| ... } -> self
7077 * permutation(count = self.size) -> new_enumerator
7079 * Iterates over permutations of the elements of +self+;
7080 * the order of permutations is indeterminate.
7082 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7083 * calls the block with each permutation of +self+ of size +count+;
7088 * a.permutation(1) {|perm| perms.push(perm) }
7089 * perms # => [[0], [1], [2]]
7092 * a.permutation(2) {|perm| perms.push(perm) }
7093 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7096 * a.permutation(3) {|perm| perms.push(perm) }
7097 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7099 * When +count+ is zero, calls the block once with a new empty array:
7102 * a.permutation(0) {|perm| perms.push(perm) }
7105 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7106 * does not call the block:
7108 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7109 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7111 * With no block given, returns a new Enumerator.
7113 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7117 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
7121 n
= RARRAY_LEN(ary
); /* Array length */
7122 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
7124 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
7125 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
7127 if (r
< 0 || n
< r
) {
7128 /* no permutations: yield nothing */
7130 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7131 rb_yield(rb_ary_new2(0));
7133 else if (r
== 1) { /* this is a special, easy case */
7134 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7135 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7138 else { /* this is the general case */
7140 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
7141 char *used
= (char*)(p
+ r
);
7142 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7143 RBASIC_CLEAR_CLASS(ary0
);
7145 MEMZERO(used
, char, n
); /* initialize array */
7147 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
7149 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7155 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
7159 MEMZERO(stack
+1, long, n
);
7162 for (lev
++; lev
< n
; lev
++) {
7163 stack
[lev
+1] = stack
[lev
]+1;
7165 if (!yield_indexed_values(values
, n
, stack
+1)) {
7166 rb_raise(rb_eRuntimeError
, "combination reentered");
7169 if (lev
== 0) return;
7171 } while (stack
[lev
+1]+n
== len
+lev
+1);
7176 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7178 long n
= RARRAY_LEN(ary
);
7179 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7181 return binomial_coefficient(k
, n
);
7186 * combination(count) {|element| ... } -> self
7187 * combination(count) -> new_enumerator
7189 * When a block and a positive
7190 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7191 * argument +count+ (<tt>0 < count <= self.size</tt>)
7192 * are given, calls the block with each combination of +self+ of size +count+;
7195 * a = %w[a b c] # => ["a", "b", "c"]
7196 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7204 * The order of the yielded combinations is not guaranteed.
7206 * When +count+ is zero, calls the block once with a new empty array:
7208 * a.combination(0) {|combination| p combination }
7209 * [].combination(0) {|combination| p combination }
7216 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7217 * does not call the block:
7219 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7220 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7222 * With no block given, returns a new Enumerator.
7224 * Related: Array#permutation;
7225 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7229 rb_ary_combination(VALUE ary
, VALUE num
)
7234 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7235 len
= RARRAY_LEN(ary
);
7236 if (n
< 0 || len
< n
) {
7240 rb_yield(rb_ary_new2(0));
7243 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7244 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7248 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7250 long *stack
= ALLOCV_N(long, t0
, n
+1);
7252 RBASIC_CLEAR_CLASS(ary0
);
7253 combinate0(len
, n
, stack
, ary0
);
7255 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7261 * Compute repeated permutations of +r+ elements of the set
7262 * <code>[0..n-1]</code>.
7264 * When we have a complete repeated permutation of array indices, copy the
7265 * values at those indices into a new array and yield that array.
7267 * n: the size of the set
7268 * r: the number of elements in each permutation
7269 * p: the array (of size r) that we're filling in
7270 * values: the Ruby array that holds the actual values to permute
7273 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7275 long i
= 0, index
= 0;
7279 if (++index
< r
-1) {
7283 for (i
= 0; i
< n
; ++i
) {
7285 if (!yield_indexed_values(values
, r
, p
)) {
7286 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7290 if (index
<= 0) return;
7291 } while ((i
= ++p
[--index
]) >= n
);
7296 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7298 long n
= RARRAY_LEN(ary
);
7299 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7305 return LONG2FIX(!k
);
7307 return rb_int_positive_pow(n
, (unsigned long)k
);
7312 * repeated_permutation(size) {|permutation| ... } -> self
7313 * repeated_permutation(size) -> new_enumerator
7315 * With a block given, calls the block with each repeated permutation of length +size+
7316 * of the elements of +self+;
7317 * each permutation is an array;
7318 * returns +self+. The order of the permutations is indeterminate.
7320 * If a positive integer argument +size+ is given,
7321 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7322 * The number of permutations is <tt>self.size**size</tt>.
7329 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7330 * p # => [[0], [1], [2]]
7335 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7336 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7338 * If +size+ is zero, calls the block once with an empty array.
7340 * If +size+ is negative, does not call the block:
7342 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7344 * With no block given, returns a new Enumerator.
7346 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7349 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7353 n
= RARRAY_LEN(ary
); /* Array length */
7354 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7355 r
= NUM2LONG(num
); /* Permutation size from argument */
7358 /* no permutations: yield nothing */
7360 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7361 rb_yield(rb_ary_new2(0));
7363 else if (r
== 1) { /* this is a special, easy case */
7364 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7365 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7368 else { /* this is the general case */
7370 long *p
= ALLOCV_N(long, t0
, r
);
7371 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7372 RBASIC_CLEAR_CLASS(ary0
);
7374 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7376 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7382 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7384 long i
= 0, index
= 0;
7388 if (++index
< r
-1) {
7392 for (; i
< n
; ++i
) {
7394 if (!yield_indexed_values(values
, r
, p
)) {
7395 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7399 if (index
<= 0) return;
7400 } while ((i
= ++p
[--index
]) >= n
);
7405 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7407 long n
= RARRAY_LEN(ary
);
7408 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7412 return binomial_coefficient(k
, n
+ k
- 1);
7417 * repeated_combination(size) {|combination| ... } -> self
7418 * repeated_combination(size) -> new_enumerator
7420 * With a block given, calls the block with each repeated combination of length +size+
7421 * of the elements of +self+;
7422 * each combination is an array;
7423 * returns +self+. The order of the combinations is indeterminate.
7425 * If a positive integer argument +size+ is given,
7426 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7427 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7434 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7435 * c # => [[0], [1], [2]]
7440 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7441 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7443 * If +size+ is zero, calls the block once with an empty array.
7445 * If +size+ is negative, does not call the block:
7447 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7449 * With no block given, returns a new Enumerator.
7451 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7455 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7459 n
= NUM2LONG(num
); /* Combination size from argument */
7460 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7461 len
= RARRAY_LEN(ary
);
7466 rb_yield(rb_ary_new2(0));
7469 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7470 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7473 else if (len
== 0) {
7478 long *p
= ALLOCV_N(long, t0
, n
);
7479 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7480 RBASIC_CLEAR_CLASS(ary0
);
7482 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7484 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7491 * product(*other_arrays) -> new_array
7492 * product(*other_arrays) {|combination| ... } -> self
7494 * Computes all combinations of elements from all the arrays,
7495 * including both +self+ and +other_arrays+:
7497 * - The number of combinations is the product of the sizes of all the arrays,
7498 * including both +self+ and +other_arrays+.
7499 * - The order of the returned combinations is indeterminate.
7501 * With no block given, returns the combinations as an array of arrays:
7503 * p = [0, 1].product([2, 3])
7504 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7506 * p = [0, 1].product([2, 3], [4, 5])
7507 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7510 * If +self+ or any argument is empty, returns an empty array:
7512 * [].product([2, 3], [4, 5]) # => []
7513 * [0, 1].product([2, 3], []) # => []
7515 * If no argument is given, returns an array of 1-element arrays,
7516 * each containing an element of +self+:
7518 * a.product # => [[0], [1], [2]]
7520 * With a block given, calls the block with each combination; returns +self+:
7523 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7524 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7526 * If +self+ or any argument is empty, does not call the block:
7528 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7530 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7533 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7536 * [0, 1].product {|combination| p.push(combination) }
7539 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7543 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7545 int n
= argc
+1; /* How many arrays we're operating on */
7546 volatile VALUE t0
= rb_ary_hidden_new(n
);
7547 volatile VALUE t1
= Qundef
;
7548 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7549 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7550 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7554 RBASIC_CLEAR_CLASS(t0
);
7556 /* initialize the arrays of arrays */
7559 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7560 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7562 /* initialize the counters for the arrays */
7563 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7565 /* Otherwise, allocate and fill in an array of results */
7566 if (rb_block_given_p()) {
7567 /* Make defensive copies of arrays; exit if any is empty */
7568 for (i
= 0; i
< n
; i
++) {
7569 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7570 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7574 /* Compute the length of the result array; return [] if any is empty */
7575 for (i
= 0; i
< n
; i
++) {
7576 long k
= RARRAY_LEN(arrays
[i
]);
7578 result
= rb_ary_new2(0);
7581 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7582 rb_raise(rb_eRangeError
, "too big to product");
7585 result
= rb_ary_new2(resultlen
);
7589 /* fill in one subarray */
7590 VALUE subarray
= rb_ary_new2(n
);
7591 for (j
= 0; j
< n
; j
++) {
7592 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7595 /* put it on the result array */
7596 if (NIL_P(result
)) {
7597 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7599 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7600 rb_raise(rb_eRuntimeError
, "product reentered");
7603 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7607 rb_ary_push(result
, subarray
);
7611 * Increment the last counter. If it overflows, reset to 0
7612 * and increment the one before it.
7616 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7618 /* If the first counter overflows, we are done */
7619 if (--m
< 0) goto done
;
7627 return NIL_P(result
) ? ary
: result
;
7632 * take(count) -> new_array
7634 * Returns a new array containing the first +count+ element of +self+
7636 * +count+ must be a non-negative numeric;
7637 * does not modify +self+:
7639 * a = ['a', 'b', 'c', 'd']
7640 * a.take(2) # => ["a", "b"]
7641 * a.take(2.1) # => ["a", "b"]
7642 * a.take(50) # => ["a", "b", "c", "d"]
7645 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7649 rb_ary_take(VALUE obj
, VALUE n
)
7651 long len
= NUM2LONG(n
);
7653 rb_raise(rb_eArgError
, "attempt to take negative size");
7655 return rb_ary_subseq(obj
, 0, len
);
7660 * take_while {|element| ... } -> new_array
7661 * take_while -> new_enumerator
7663 * With a block given, calls the block with each successive element of +self+;
7664 * stops iterating if the block returns +false+ or +nil+;
7665 * returns a new array containing those elements for which the block returned a truthy value:
7667 * a = [0, 1, 2, 3, 4, 5]
7668 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7669 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7670 * a.take_while {|element| false } # => []
7672 * With no block given, returns a new Enumerator.
7674 * Does not modify +self+.
7676 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7680 rb_ary_take_while(VALUE ary
)
7684 RETURN_ENUMERATOR(ary
, 0, 0);
7685 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7686 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7688 return rb_ary_take(ary
, LONG2FIX(i
));
7693 * drop(count) -> new_array
7695 * Returns a new array containing all but the first +count+ element of +self+,
7696 * where +count+ is a non-negative integer;
7697 * does not modify +self+.
7701 * a = [0, 1, 2, 3, 4, 5]
7702 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7703 * a.drop(1) # => [1, 2, 3, 4, 5]
7704 * a.drop(2) # => [2, 3, 4, 5]
7707 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7711 rb_ary_drop(VALUE ary
, VALUE n
)
7714 long pos
= NUM2LONG(n
);
7716 rb_raise(rb_eArgError
, "attempt to drop negative size");
7719 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7720 if (NIL_P(result
)) result
= rb_ary_new();
7726 * drop_while {|element| ... } -> new_array
7727 * drop_while -> new_enumerator
7729 * With a block given, calls the block with each successive element of +self+;
7730 * stops if the block returns +false+ or +nil+;
7731 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7732 * does not modify +self+:
7734 * a = [0, 1, 2, 3, 4, 5]
7735 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7737 * With no block given, returns a new Enumerator.
7739 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7743 rb_ary_drop_while(VALUE ary
)
7747 RETURN_ENUMERATOR(ary
, 0, 0);
7748 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7749 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7751 return rb_ary_drop(ary
, LONG2FIX(i
));
7756 * any? -> true or false
7757 * any?(object) -> true or false
7758 * any? {|element| ... } -> true or false
7760 * Returns whether for any element of +self+, a given criterion is satisfied.
7762 * With no block and no argument, returns whether any element of +self+ is truthy:
7764 * [nil, false, []].any? # => true # Array object is truthy.
7765 * [nil, false, {}].any? # => true # Hash object is truthy.
7766 * [nil, false, ''].any? # => true # String object is truthy.
7767 * [nil, false].any? # => false # Nil and false are not truthy.
7769 * With argument +object+ given,
7770 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7772 * [nil, false, 0].any?(0) # => true
7773 * [nil, false, 1].any?(0) # => false
7774 * [nil, false, 'food'].any?(/foo/) # => true
7775 * [nil, false, 'food'].any?(/bar/) # => false
7777 * With a block given,
7778 * calls the block with each element in +self+;
7779 * returns whether the block returns any truthy value:
7781 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7782 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7784 * With both a block and argument +object+ given,
7785 * ignores the block and uses +object+ as above.
7787 * <b>Special case</b>: returns +false+ if +self+ is empty
7788 * (regardless of any given argument or block).
7790 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7794 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7796 long i
, len
= RARRAY_LEN(ary
);
7798 rb_check_arity(argc
, 0, 1);
7799 if (!len
) return Qfalse
;
7801 if (rb_block_given_p()) {
7802 rb_warn("given block not used");
7804 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7805 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7808 else if (!rb_block_given_p()) {
7809 for (i
= 0; i
< len
; ++i
) {
7810 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7814 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7815 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7823 * all? -> true or false
7824 * all?(object) -> true or false
7825 * all? {|element| ... } -> true or false
7827 * Returns whether for every element of +self+,
7828 * a given criterion is satisfied.
7830 * With no block and no argument,
7831 * returns whether every element of +self+ is truthy:
7833 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7834 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7835 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7837 * With argument +object+ given, returns whether <tt>object === ele</tt>
7838 * for every element +ele+ in +self+:
7840 * [0, 0, 0].all?(0) # => true
7841 * [0, 1, 2].all?(1) # => false
7842 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7843 * ['food', 'drink'].all?(/foo/) # => false
7845 * With a block given, calls the block with each element in +self+;
7846 * returns whether the block returns only truthy values:
7848 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7849 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7851 * With both a block and argument +object+ given,
7852 * ignores the block and uses +object+ as above.
7854 * <b>Special case</b>: returns +true+ if +self+ is empty
7855 * (regardless of any given argument or block).
7857 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7861 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7863 long i
, len
= RARRAY_LEN(ary
);
7865 rb_check_arity(argc
, 0, 1);
7866 if (!len
) return Qtrue
;
7868 if (rb_block_given_p()) {
7869 rb_warn("given block not used");
7871 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7872 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7875 else if (!rb_block_given_p()) {
7876 for (i
= 0; i
< len
; ++i
) {
7877 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7881 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7882 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7890 * none? -> true or false
7891 * none?(object) -> true or false
7892 * none? {|element| ... } -> true or false
7894 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7896 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7897 * +false+ otherwise:
7899 * [nil, false].none? # => true
7900 * [nil, 0, false].none? # => false
7901 * [].none? # => true
7903 * With argument +object+ given, returns +false+ if for any element +element+,
7904 * <tt>object === element</tt>; +true+ otherwise:
7906 * ['food', 'drink'].none?(/bar/) # => true
7907 * ['food', 'drink'].none?(/foo/) # => false
7908 * [].none?(/foo/) # => true
7909 * [0, 1, 2].none?(3) # => true
7910 * [0, 1, 2].none?(1) # => false
7912 * With a block given, calls the block with each element in +self+;
7913 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7915 * [0, 1, 2].none? {|element| element > 3 } # => true
7916 * [0, 1, 2].none? {|element| element > 1 } # => false
7918 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7922 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7924 long i
, len
= RARRAY_LEN(ary
);
7926 rb_check_arity(argc
, 0, 1);
7927 if (!len
) return Qtrue
;
7929 if (rb_block_given_p()) {
7930 rb_warn("given block not used");
7932 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7933 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7936 else if (!rb_block_given_p()) {
7937 for (i
= 0; i
< len
; ++i
) {
7938 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7942 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7943 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7951 * one? -> true or false
7952 * one? {|element| ... } -> true or false
7953 * one?(object) -> true or false
7955 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7957 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7958 * +false+ otherwise:
7960 * [nil, 0].one? # => true
7961 * [0, 0].one? # => false
7962 * [nil, nil].one? # => false
7963 * [].one? # => false
7965 * With a block given, calls the block with each element in +self+;
7966 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7968 * [0, 1, 2].one? {|element| element > 0 } # => false
7969 * [0, 1, 2].one? {|element| element > 1 } # => true
7970 * [0, 1, 2].one? {|element| element > 2 } # => false
7972 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7973 * +false+ otherwise:
7975 * [0, 1, 2].one?(0) # => true
7976 * [0, 0, 1].one?(0) # => false
7977 * [1, 1, 2].one?(0) # => false
7978 * ['food', 'drink'].one?(/bar/) # => false
7979 * ['food', 'drink'].one?(/foo/) # => true
7980 * [].one?(/foo/) # => false
7982 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7986 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7988 long i
, len
= RARRAY_LEN(ary
);
7989 VALUE result
= Qfalse
;
7991 rb_check_arity(argc
, 0, 1);
7992 if (!len
) return Qfalse
;
7994 if (rb_block_given_p()) {
7995 rb_warn("given block not used");
7997 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7998 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7999 if (result
) return Qfalse
;
8004 else if (!rb_block_given_p()) {
8005 for (i
= 0; i
< len
; ++i
) {
8006 if (RTEST(RARRAY_AREF(ary
, i
))) {
8007 if (result
) return Qfalse
;
8013 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
8014 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
8015 if (result
) return Qfalse
;
8025 * dig(index, *identifiers) -> object
8027 * Finds and returns the object in nested object
8028 * specified by +index+ and +identifiers+;
8029 * the nested objects may be instances of various classes.
8030 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8034 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8035 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8036 * a.dig(1, 2) # => [:bat, :bam]
8037 * a.dig(1, 2, 0) # => :bat
8038 * a.dig(1, 2, 3) # => nil
8040 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8044 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
8046 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
8047 self
= rb_ary_at(self
, *argv
);
8048 if (!--argc
) return self
;
8050 return rb_obj_dig(argc
, argv
, self
, Qnil
);
8054 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
8057 v
= rb_fix_plus(LONG2FIX(n
), v
);
8059 v
= rb_rational_plus(r
, v
);
8062 v
= rb_fix_plus(LONG2FIX(0), v
);
8069 * sum(init = 0) -> object
8070 * sum(init = 0) {|element| ... } -> object
8072 * With no block given, returns the sum of +init+ and all elements of +self+;
8073 * for array +array+ and value +init+, equivalent to:
8076 * array.each {|element| sum += element }
8079 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8083 * [0, 1, 2, 3].sum # => 6
8084 * [0, 1, 2, 3].sum(100) # => 106
8085 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8086 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8087 * # => [2, 3, :foo, :bar, "foo", "bar"]
8089 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8091 * # Raises TypeError: Array can't be coerced into Integer.
8092 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8094 * With a block given, calls the block with each element of +self+;
8095 * the block's return value (instead of the element itself) is used as the addend:
8097 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8098 * # => "Coerced and concatenated: zero1two"
8102 * - Array#join and Array#flatten may be faster than Array#sum
8103 * for an array of strings or an array of arrays.
8104 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8109 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
8115 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
8117 block_given
= rb_block_given_p();
8119 if (RARRAY_LEN(ary
) == 0)
8125 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
8127 goto init_is_a_value
;
8130 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
8131 e
= RARRAY_AREF(ary
, i
);
8135 n
+= FIX2LONG(e
); /* should not overflow long type */
8137 v
= rb_big_plus(LONG2NUM(n
), v
);
8141 else if (RB_BIGNUM_TYPE_P(e
))
8142 v
= rb_big_plus(e
, v
);
8143 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8147 r
= rb_rational_plus(r
, e
);
8152 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8156 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8158 if (RB_FLOAT_TYPE_P(e
)) {
8160 * Kahan-Babuska balancing compensated summation algorithm
8161 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8168 goto has_float_value
;
8169 for (; i
< RARRAY_LEN(ary
); i
++) {
8170 e
= RARRAY_AREF(ary
, i
);
8173 if (RB_FLOAT_TYPE_P(e
))
8175 x
= RFLOAT_VALUE(e
);
8176 else if (FIXNUM_P(e
))
8178 else if (RB_BIGNUM_TYPE_P(e
))
8180 else if (RB_TYPE_P(e
, T_RATIONAL
))
8185 if (isnan(f
)) continue;
8191 if (isinf(f
) && signbit(x
) != signbit(f
))
8197 if (isinf(f
)) continue;
8200 if (fabs(f
) >= fabs(x
))
8213 goto has_some_value
;
8215 for (; i
< RARRAY_LEN(ary
); i
++) {
8216 e
= RARRAY_AREF(ary
, i
);
8220 v
= rb_funcall(v
, idPLUS
, 1, e
);
8227 rb_ary_deconstruct(VALUE ary
)
8233 * An \Array object is an ordered, integer-indexed collection of objects,
8234 * called _elements_;
8235 * the object represents
8236 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8238 * An element may be any object (even another array);
8239 * elements may be any mixture of objects of different types.
8241 * Important data structures that use arrays include:
8243 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8244 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8245 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8246 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8247 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8248 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8249 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8251 * There are also array-like data structures:
8253 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8254 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8255 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8256 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8257 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8261 * \Array indexing starts at 0, as in C or Java.
8263 * A non-negative index is an offset from the first element:
8265 * - Index 0 indicates the first element.
8266 * - Index 1 indicates the second element.
8269 * A negative index is an offset, backwards, from the end of the array:
8271 * - Index -1 indicates the last element.
8272 * - Index -2 indicates the next-to-last element.
8276 * === In-Range and Out-of-Range Indexes
8278 * A non-negative index is <i>in range</i> if and only if it is smaller than
8279 * the size of the array. For a 3-element array:
8281 * - Indexes 0 through 2 are in range.
8282 * - Index 3 is out of range.
8284 * A negative index is <i>in range</i> if and only if its absolute value is
8285 * not larger than the size of the array. For a 3-element array:
8287 * - Indexes -1 through -3 are in range.
8288 * - Index -4 is out of range.
8290 * === Effective Index
8292 * Although the effective index into an array is always an integer,
8293 * some methods (both within class \Array and elsewhere)
8294 * accept one or more non-integer arguments that are
8295 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8297 * == Creating Arrays
8299 * You can create an \Array object explicitly with:
8301 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8303 * [1, 'one', :one, [2, 'two', :two]]
8305 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8307 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8308 * %w[1 % *] # => ["1", "%", "*"]
8310 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8312 * %i[foo bar baz] # => [:foo, :bar, :baz]
8313 * %i[1 % *] # => [:"1", :%, :*]
8315 * - Method Kernel#Array:
8317 * Array(["a", "b"]) # => ["a", "b"]
8318 * Array(1..5) # => [1, 2, 3, 4, 5]
8319 * Array(key: :value) # => [[:key, :value]]
8320 * Array(nil) # => []
8322 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8324 * - Method Array.new:
8327 * Array.new(3) # => [nil, nil, nil]
8328 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8329 * Array.new(3, true) # => [true, true, true]
8331 * Note that the last example above populates the array
8332 * with references to the same object.
8333 * This is recommended only in cases where that object is a natively immutable object
8334 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8336 * Another way to create an array with various objects, using a block;
8337 * this usage is safe for mutable objects such as hashes, strings or
8340 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8342 * Here is a way to create a multi-dimensional array:
8344 * Array.new(3) {Array.new(3)}
8345 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8347 * A number of Ruby methods, both in the core and in the standard library,
8348 * provide instance method +to_a+, which converts an object to an array.
8356 * - OptionParser#to_a
8361 * - Benchmark::Tms#to_a
8363 * - Enumerator::Lazy#to_a
8365 * - Gem::NameTuple#to_a
8366 * - Gem::Platform#to_a
8367 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8368 * - Gem::SourceList#to_a
8369 * - OpenSSL::X509::Extension#to_a
8370 * - OpenSSL::X509::Name#to_a
8372 * - Rinda::RingFinger#to_a
8373 * - Ripper::Lexer::Elem#to_a
8374 * - RubyVM::InstructionSequence#to_a
8379 * In addition to the methods it mixes in through the Enumerable module,
8380 * class \Array has proprietary methods for accessing, searching and otherwise
8381 * manipulating arrays.
8383 * Some of the more common ones are illustrated below.
8385 * == Accessing Elements
8387 * Elements in an array can be retrieved using the Array#[] method. It can
8388 * take a single integer argument (a numeric index), a pair of arguments
8389 * (start and length) or a range. Negative indices start counting from the end,
8390 * with -1 being the last element.
8392 * arr = [1, 2, 3, 4, 5, 6]
8396 * arr[2, 3] #=> [3, 4, 5]
8397 * arr[1..4] #=> [2, 3, 4, 5]
8398 * arr[1..-3] #=> [2, 3, 4]
8400 * Another way to access a particular array element is by using the #at method
8404 * The #slice method works in an identical manner to Array#[].
8406 * To raise an error for indices outside of the array bounds or else to
8407 * provide a default value when that happens, you can use #fetch.
8409 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8410 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8411 * arr.fetch(100, "oops") #=> "oops"
8413 * The special methods #first and #last will return the first and last
8414 * elements of an array, respectively.
8419 * To return the first +n+ elements of an array, use #take
8421 * arr.take(3) #=> [1, 2, 3]
8423 * #drop does the opposite of #take, by returning the elements after +n+
8424 * elements have been dropped:
8426 * arr.drop(3) #=> [4, 5, 6]
8428 * == Obtaining Information about an \Array
8430 * An array keeps track of its own length at all times. To query an array
8431 * about the number of elements it contains, use #length, #count or #size.
8433 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8434 * browsers.length #=> 5
8435 * browsers.count #=> 5
8437 * To check whether an array contains any elements at all
8439 * browsers.empty? #=> false
8441 * To check whether a particular item is included in the array
8443 * browsers.include?('Konqueror') #=> false
8445 * == Adding Items to an \Array
8447 * Items can be added to the end of an array by using either #push or #<<
8449 * arr = [1, 2, 3, 4]
8450 * arr.push(5) #=> [1, 2, 3, 4, 5]
8451 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8453 * #unshift will add a new item to the beginning of an array.
8455 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8457 * With #insert you can add a new element to an array at any position.
8459 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8461 * Using the #insert method, you can also insert multiple values at once:
8463 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8464 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8466 * == Removing Items from an \Array
8468 * The method #pop removes the last element in an array and returns it:
8470 * arr = [1, 2, 3, 4, 5, 6]
8472 * arr #=> [1, 2, 3, 4, 5]
8474 * To retrieve and at the same time remove the first item, use #shift:
8477 * arr #=> [2, 3, 4, 5]
8479 * To delete an element at a particular index:
8481 * arr.delete_at(2) #=> 4
8484 * To delete a particular element anywhere in an array, use #delete:
8486 * arr = [1, 2, 2, 3]
8487 * arr.delete(2) #=> 2
8490 * A useful method if you need to remove +nil+ values from an array is
8493 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8494 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8495 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8496 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8497 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8499 * Another common need is to remove duplicate elements from an array.
8501 * It has the non-destructive #uniq, and destructive method #uniq!
8503 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8504 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8506 * == Iterating over an \Array
8508 * Like all classes that include the Enumerable module, class \Array has an each
8509 * method, which defines what elements should be iterated over and how. In
8510 * case of Array#each, all elements in +self+ are yielded to
8511 * the supplied block in sequence.
8513 * Note that this operation leaves the array unchanged.
8515 * arr = [1, 2, 3, 4, 5]
8516 * arr.each {|a| print a -= 10, " "}
8517 * # prints: -9 -8 -7 -6 -5
8518 * #=> [1, 2, 3, 4, 5]
8520 * Another sometimes useful iterator is #reverse_each which will iterate over
8521 * the elements in the array in reverse order.
8523 * words = %w[first second third fourth fifth sixth]
8525 * words.reverse_each {|word| str += "#{word} "}
8526 * p str #=> "sixth fifth fourth third second first "
8528 * The #map method can be used to create a new array based on the original
8529 * array, but with the values modified by the supplied block:
8531 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8532 * arr #=> [1, 2, 3, 4, 5]
8533 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8534 * arr #=> [1, 4, 9, 16, 25]
8537 * == Selecting Items from an \Array
8539 * Elements can be selected from an array according to criteria defined in a
8540 * block. The selection can happen in a destructive or a non-destructive
8541 * manner. While the destructive operations will modify the array they were
8542 * called on, the non-destructive methods usually return a new array with the
8543 * selected elements, but leave the original array unchanged.
8545 * === Non-destructive Selection
8547 * arr = [1, 2, 3, 4, 5, 6]
8548 * arr.select {|a| a > 3} #=> [4, 5, 6]
8549 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8550 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8551 * arr #=> [1, 2, 3, 4, 5, 6]
8553 * === Destructive Selection
8555 * #select! and #reject! are the corresponding destructive methods to #select
8558 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8559 * opposite result when supplied with the same block:
8561 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8564 * arr = [1, 2, 3, 4, 5, 6]
8565 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8570 * First, what's elsewhere. Class \Array:
8572 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8573 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8574 * which provides dozens of additional methods.
8576 * Here, class \Array provides methods that are useful for:
8578 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8579 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8580 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8581 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8582 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8583 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8584 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8585 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8586 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8587 * - {And more....}[rdoc-ref:Array@Other+Methods]
8589 * === Methods for Creating an \Array
8591 * - ::[]: Returns a new array populated with given objects.
8592 * - ::new: Returns a new array.
8593 * - ::try_convert: Returns a new array created from a given object.
8595 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8597 * === Methods for Querying
8599 * - #all?: Returns whether all elements meet a given criterion.
8600 * - #any?: Returns whether any element meets a given criterion.
8601 * - #count: Returns the count of elements that meet a given criterion.
8602 * - #empty?: Returns whether there are no elements.
8603 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8604 * - #hash: Returns the integer hash code.
8605 * - #include?: Returns whether any element <tt>==</tt> a given object.
8606 * - #length (aliased as #size): Returns the count of elements.
8607 * - #none?: Returns whether no element <tt>==</tt> a given object.
8608 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8609 * - #rindex: Returns the index of the last element that meets a given criterion.
8611 * === Methods for Comparing
8613 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8614 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8615 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8617 * === Methods for Fetching
8619 * These methods do not modify +self+.
8621 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8622 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8623 * - #at: Returns the element at a given offset.
8624 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8625 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8626 * - #compact: Returns an array containing all non-+nil+ elements.
8627 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8628 * - #drop: Returns trailing elements as determined by a given index.
8629 * - #drop_while: Returns trailing elements as determined by a given block.
8630 * - #fetch: Returns the element at a given offset.
8631 * - #fetch_values: Returns elements at given offsets.
8632 * - #first: Returns one or more leading elements.
8633 * - #last: Returns one or more trailing elements.
8634 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8635 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8636 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8637 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8638 * - #reject: Returns an array containing elements not rejected by a given block.
8639 * - #reverse: Returns all elements in reverse order.
8640 * - #rotate: Returns all elements with some rotated from one end to the other.
8641 * - #sample: Returns one or more random elements.
8642 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8643 * - #shuffle: Returns elements in a random order.
8644 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8645 * - #take: Returns leading elements as determined by a given index.
8646 * - #take_while: Returns leading elements as determined by a given block.
8647 * - #uniq: Returns an array containing non-duplicate elements.
8648 * - #values_at: Returns the elements at given offsets.
8650 * === Methods for Assigning
8652 * These methods add, replace, or reorder elements in +self+.
8654 * - #<<: Appends an element.
8655 * - #[]=: Assigns specified elements with a given object.
8656 * - #concat: Appends all elements from given arrays.
8657 * - #fill: Replaces specified elements with specified objects.
8658 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8659 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8660 * - #insert: Inserts given objects at a given offset; does not replace elements.
8661 * - #push (aliased as #append): Appends elements.
8662 * - #reverse!: Replaces +self+ with its elements reversed.
8663 * - #rotate!: Replaces +self+ with its elements rotated.
8664 * - #shuffle!: Replaces +self+ with its elements in random order.
8665 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8666 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8667 * - #unshift (aliased as #prepend): Prepends leading elements.
8669 * === Methods for Deleting
8671 * Each of these methods removes elements from +self+:
8673 * - #clear: Removes all elements.
8674 * - #compact!: Removes all +nil+ elements.
8675 * - #delete: Removes elements equal to a given object.
8676 * - #delete_at: Removes the element at a given offset.
8677 * - #delete_if: Removes elements specified by a given block.
8678 * - #keep_if: Removes elements not specified by a given block.
8679 * - #pop: Removes and returns the last element.
8680 * - #reject!: Removes elements specified by a given block.
8681 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8682 * - #shift: Removes and returns the first element.
8683 * - #slice!: Removes and returns a sequence of elements.
8684 * - #uniq!: Removes duplicates.
8686 * === Methods for Combining
8688 * - #&: Returns an array containing elements found both in +self+ and a given array.
8689 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8690 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8691 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8692 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8693 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8694 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8695 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8696 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8698 * === Methods for Iterating
8700 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8701 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8702 * - #each: Passes each element to a given block.
8703 * - #each_index: Passes each element index to a given block.
8704 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8705 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8706 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8707 * - #reverse_each: Passes each element, in reverse order, to a given block.
8709 * === Methods for Converting
8711 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8712 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8713 * - #flatten: Returns an array that is a recursive flattening of +self+.
8714 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8715 * - #join: Returns a newsString containing the elements joined by the field separator.
8716 * - #to_a: Returns +self+ or a new array containing all elements.
8717 * - #to_ary: Returns +self+.
8718 * - #to_h: Returns a new hash formed from the elements.
8719 * - #transpose: Transposes +self+, which must be an array of arrays.
8720 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8724 * - #*: Returns one of the following:
8726 * - With integer argument +n+, a new array that is the concatenation
8727 * of +n+ copies of +self+.
8728 * - With string argument +field_separator+, a new string that is equivalent to
8729 * <tt>join(field_separator)</tt>.
8731 * - #pack: Packs the elements into a binary sequence.
8732 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8738 fake_ary_flags
= init_fake_ary_flags();
8740 rb_cArray
= rb_define_class("Array", rb_cObject
);
8741 rb_include_module(rb_cArray
, rb_mEnumerable
);
8743 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8744 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8745 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8746 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8747 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8748 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8750 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8751 rb_define_alias(rb_cArray
, "to_s", "inspect");
8752 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8753 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8754 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8756 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8757 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8758 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8760 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8761 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8762 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8763 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8764 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8765 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8766 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8767 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8768 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8769 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8770 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8771 rb_define_alias(rb_cArray
, "append", "push");
8772 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8773 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8774 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8775 rb_define_alias(rb_cArray
, "prepend", "unshift");
8776 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8777 rb_define_method(rb_cArray
, "each", rb_ary_each
, 0);
8778 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8779 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8780 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8781 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8782 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8783 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8784 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8785 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8786 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8787 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8788 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8789 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8790 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8791 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8792 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8793 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8794 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8795 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8796 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8797 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8798 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8799 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8800 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8801 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8802 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8803 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8804 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8805 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8806 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8807 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8808 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8809 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8810 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8811 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8812 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8813 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8814 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8815 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8817 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8818 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8820 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8821 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8823 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8824 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8826 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8827 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8828 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8830 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8831 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8832 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8834 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8835 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8836 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8837 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8838 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8839 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8840 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8841 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8842 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8843 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8844 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8845 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8846 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8848 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8849 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8850 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8851 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8852 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8853 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8854 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8855 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8856 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8857 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8858 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8859 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8860 rb_define_method(rb_cArray
, "freeze", rb_ary_freeze
, 0);
8862 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8864 rb_cArray_empty_frozen
= rb_ary_freeze(rb_ary_new());
8865 rb_vm_register_global_object(rb_cArray_empty_frozen
);
8868 #include "array.rbinc"