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/util.h"
38 #include "ruby_assert.h"
41 VALUE rb_cArray_empty_frozen
;
45 * 1: RARRAY_EMBED_FLAG
46 * The array is embedded (its contents follow the header, rather than
47 * being on a separately allocated buffer).
48 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
49 * The array is shared. The buffer this array points to is owned by
50 * another array (the shared root).
51 * 3-9: RARRAY_EMBED_LEN
52 * The length of the array when RARRAY_EMBED_FLAG is set.
53 * 12: RARRAY_SHARED_ROOT_FLAG
54 * The array is a shared root that does reference counting. The buffer
55 * this array points to is owned by this array but may be pointed to
57 * Note: Frozen arrays may be a shared root without this flag being
58 * set. Frozen arrays do not have reference counting because
59 * they cannot be modified. Not updating the reference count
60 * improves copy-on-write performance. Their reference count is
61 * assumed to be infinity.
62 * 14: RARRAY_PTR_IN_USE_FLAG
63 * The buffer of the array is in use. This is only used during
67 /* for OPTIMIZED_CMP: */
70 #define ARY_DEFAULT_SIZE 16
71 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
72 #define SMALL_ARRAY_LEN 16
74 RBIMPL_ATTR_MAYBE_UNUSED()
76 should_be_T_ARRAY(VALUE ary
)
78 return RB_TYPE_P(ary
, T_ARRAY
);
81 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
82 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
83 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
84 RARRAY(a)->as.heap.aux.capa)
86 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
87 #define ARY_EMBED_LEN(a) \
88 (RUBY_ASSERT(ARY_EMBED_P(a)), \
89 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
90 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
91 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
93 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
94 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
96 #define FL_SET_EMBED(a) do { \
97 RUBY_ASSERT(!ARY_SHARED_P(a)); \
98 FL_SET((a), RARRAY_EMBED_FLAG); \
102 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
103 #define FL_SET_SHARED(ary) do { \
104 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
105 FL_SET((ary), RARRAY_SHARED_FLAG); \
107 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
109 #define ARY_SET_PTR(ary, p) do { \
110 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
111 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
112 RARRAY(ary)->as.heap.ptr = (p); \
114 #define ARY_SET_EMBED_LEN(ary, n) do { \
116 RUBY_ASSERT(ARY_EMBED_P(ary)); \
117 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
118 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
120 #define ARY_SET_HEAP_LEN(ary, n) do { \
121 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
122 RARRAY(ary)->as.heap.len = (n); \
124 #define ARY_SET_LEN(ary, n) do { \
125 if (ARY_EMBED_P(ary)) { \
126 ARY_SET_EMBED_LEN((ary), (n)); \
129 ARY_SET_HEAP_LEN((ary), (n)); \
131 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
133 #define ARY_INCREASE_PTR(ary, n) do { \
134 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
135 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
136 RARRAY(ary)->as.heap.ptr += (n); \
138 #define ARY_INCREASE_LEN(ary, n) do { \
139 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
140 if (ARY_EMBED_P(ary)) { \
141 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
144 RARRAY(ary)->as.heap.len += (n); \
148 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
149 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
150 #define ARY_SET_CAPA(ary, n) do { \
151 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
152 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
153 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
154 RARRAY(ary)->as.heap.aux.capa = (n); \
157 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
158 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
159 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
160 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
161 RUBY_ASSERT((value) >= 0); \
162 RARRAY(ary)->as.heap.aux.capa = (value); \
164 #define FL_SET_SHARED_ROOT(ary) do { \
165 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
166 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
167 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
171 ARY_SET(VALUE a
, long i
, VALUE v
)
173 RUBY_ASSERT(!ARY_SHARED_P(a
));
174 RUBY_ASSERT(!OBJ_FROZEN(a
));
176 RARRAY_ASET(a
, i
, v
);
181 ary_embed_capa(VALUE ary
)
183 size_t size
= rb_gc_obj_slot_size(ary
) - offsetof(struct RArray
, as
.ary
);
184 RUBY_ASSERT(size
% sizeof(VALUE
) == 0);
185 return size
/ sizeof(VALUE
);
189 ary_embed_size(long capa
)
191 return offsetof(struct RArray
, as
.ary
) + (sizeof(VALUE
) * capa
);
195 ary_embeddable_p(long capa
)
197 return rb_gc_size_allocatable_p(ary_embed_size(capa
));
201 rb_ary_embeddable_p(VALUE ary
)
203 /* An array cannot be turned embeddable when the array is:
204 * - Shared root: other objects may point to the buffer of this array
205 * so we cannot make it embedded.
206 * - Frozen: this array may also be a shared root without the shared root
208 * - Shared: we don't want to re-embed an array that points to a shared
209 * root (to save memory).
211 return !(ARY_SHARED_ROOT_P(ary
) || OBJ_FROZEN(ary
) || ARY_SHARED_P(ary
));
215 rb_ary_size_as_embedded(VALUE ary
)
219 if (ARY_EMBED_P(ary
)) {
220 real_size
= ary_embed_size(ARY_EMBED_LEN(ary
));
222 else if (rb_ary_embeddable_p(ary
)) {
223 real_size
= ary_embed_size(ARY_HEAP_CAPA(ary
));
226 real_size
= sizeof(struct RArray
);
233 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
236 ary_verify_(VALUE ary
, const char *file
, int line
)
238 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
240 if (ARY_SHARED_P(ary
)) {
241 VALUE root
= ARY_SHARED_ROOT(ary
);
242 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
243 const VALUE
*root_ptr
= RARRAY_CONST_PTR(root
);
244 long len
= ARY_HEAP_LEN(ary
), root_len
= RARRAY_LEN(root
);
245 RUBY_ASSERT(ARY_SHARED_ROOT_P(root
) || OBJ_FROZEN(root
));
246 RUBY_ASSERT(root_ptr
<= ptr
&& ptr
+ len
<= root_ptr
+ root_len
);
249 else if (ARY_EMBED_P(ary
)) {
250 RUBY_ASSERT(!ARY_SHARED_P(ary
));
251 RUBY_ASSERT(RARRAY_LEN(ary
) <= ary_embed_capa(ary
));
254 const VALUE
*ptr
= RARRAY_CONST_PTR(ary
);
255 long i
, len
= RARRAY_LEN(ary
);
257 if (len
> 1) len
= 1; /* check only HEAD */
258 for (i
=0; i
<len
; i
++) {
259 v
= ptr
[i
]; /* access check */
268 rb_ary_verify(VALUE ary
)
273 #define ary_verify(ary) ((void)0)
277 rb_ary_ptr_use_start(VALUE ary
)
280 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
282 return (VALUE
*)RARRAY_CONST_PTR(ary
);
286 rb_ary_ptr_use_end(VALUE ary
)
289 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
294 rb_mem_clear(VALUE
*mem
, long size
)
302 ary_mem_clear(VALUE ary
, long beg
, long size
)
304 RARRAY_PTR_USE(ary
, ptr
, {
305 rb_mem_clear(ptr
+ beg
, size
);
310 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
318 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
320 RARRAY_PTR_USE(ary
, ptr
, {
321 memfill(ptr
+ beg
, size
, val
);
322 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
327 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
329 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary
));
331 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
332 rb_gc_writebarrier_remember(buff_owner_ary
);
333 RARRAY_PTR_USE(ary
, ptr
, {
334 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
339 RARRAY_PTR_USE(ary
, ptr
, {
340 for (i
=0; i
<argc
; i
++) {
341 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
348 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
350 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
354 ary_heap_alloc_buffer(size_t capa
)
356 return ALLOC_N(VALUE
, capa
);
360 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
362 ruby_sized_xfree((void *)ptr
, size
);
366 ary_heap_free(VALUE ary
)
368 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
372 ary_heap_realloc(VALUE ary
, size_t new_capa
)
374 RUBY_ASSERT(!OBJ_FROZEN(ary
));
375 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, ARY_HEAP_CAPA(ary
));
382 rb_ary_make_embedded(VALUE ary
)
384 RUBY_ASSERT(rb_ary_embeddable_p(ary
));
385 if (!ARY_EMBED_P(ary
)) {
386 const VALUE
*buf
= ARY_HEAP_PTR(ary
);
387 long len
= ARY_HEAP_LEN(ary
);
390 ARY_SET_EMBED_LEN(ary
, len
);
392 MEMCPY((void *)ARY_EMBED_PTR(ary
), (void *)buf
, VALUE
, len
);
394 ary_heap_free_ptr(ary
, buf
, len
* sizeof(VALUE
));
399 ary_resize_capa(VALUE ary
, long capacity
)
401 RUBY_ASSERT(RARRAY_LEN(ary
) <= capacity
);
402 RUBY_ASSERT(!OBJ_FROZEN(ary
));
403 RUBY_ASSERT(!ARY_SHARED_P(ary
));
405 if (capacity
> ary_embed_capa(ary
)) {
406 size_t new_capa
= capacity
;
407 if (ARY_EMBED_P(ary
)) {
408 long len
= ARY_EMBED_LEN(ary
);
409 VALUE
*ptr
= ary_heap_alloc_buffer(capacity
);
411 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
413 ARY_SET_PTR(ary
, ptr
);
414 ARY_SET_HEAP_LEN(ary
, len
);
417 new_capa
= ary_heap_realloc(ary
, capacity
);
419 ARY_SET_CAPA(ary
, new_capa
);
422 if (!ARY_EMBED_P(ary
)) {
423 long len
= ARY_HEAP_LEN(ary
);
424 long old_capa
= ARY_HEAP_CAPA(ary
);
425 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
427 if (len
> capacity
) len
= capacity
;
428 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
429 ary_heap_free_ptr(ary
, ptr
, old_capa
);
432 ARY_SET_LEN(ary
, len
);
440 ary_shrink_capa(VALUE ary
)
442 long capacity
= ARY_HEAP_LEN(ary
);
443 long old_capa
= ARY_HEAP_CAPA(ary
);
444 RUBY_ASSERT(!ARY_SHARED_P(ary
));
445 RUBY_ASSERT(old_capa
>= capacity
);
446 if (old_capa
> capacity
) {
447 size_t new_capa
= ary_heap_realloc(ary
, capacity
);
448 ARY_SET_CAPA(ary
, new_capa
);
455 ary_double_capa(VALUE ary
, long min
)
457 long new_capa
= ARY_CAPA(ary
) / 2;
459 if (new_capa
< ARY_DEFAULT_SIZE
) {
460 new_capa
= ARY_DEFAULT_SIZE
;
462 if (new_capa
>= ARY_MAX_SIZE
- min
) {
463 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
466 ary_resize_capa(ary
, new_capa
);
472 rb_ary_decrement_share(VALUE shared_root
)
474 if (!OBJ_FROZEN(shared_root
)) {
475 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
476 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
- 1);
481 rb_ary_unshare(VALUE ary
)
483 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
484 rb_ary_decrement_share(shared_root
);
485 FL_UNSET_SHARED(ary
);
489 rb_ary_reset(VALUE ary
)
491 if (ARY_OWNS_HEAP_P(ary
)) {
494 else if (ARY_SHARED_P(ary
)) {
499 ARY_SET_EMBED_LEN(ary
, 0);
503 rb_ary_increment_share(VALUE shared_root
)
505 if (!OBJ_FROZEN(shared_root
)) {
506 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
507 RUBY_ASSERT(num
>= 0);
508 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
514 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
516 RUBY_ASSERT(!ARY_EMBED_P(ary
));
517 RUBY_ASSERT(!OBJ_FROZEN(ary
));
518 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root
) || OBJ_FROZEN(shared_root
));
520 rb_ary_increment_share(shared_root
);
522 RB_OBJ_WRITE(ary
, &RARRAY(ary
)->as
.heap
.aux
.shared_root
, shared_root
);
524 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
528 rb_ary_modify_check(VALUE ary
)
530 rb_check_frozen(ary
);
535 rb_ary_cancel_sharing(VALUE ary
)
537 if (ARY_SHARED_P(ary
)) {
538 long shared_len
, len
= RARRAY_LEN(ary
);
539 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
541 ary_verify(shared_root
);
543 if (len
<= ary_embed_capa(ary
)) {
544 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
545 FL_UNSET_SHARED(ary
);
547 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
548 rb_ary_decrement_share(shared_root
);
549 ARY_SET_EMBED_LEN(ary
, len
);
551 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
552 long shift
= RARRAY_CONST_PTR(ary
) - RARRAY_CONST_PTR(shared_root
);
553 FL_UNSET_SHARED(ary
);
554 ARY_SET_PTR(ary
, RARRAY_CONST_PTR(shared_root
));
555 ARY_SET_CAPA(ary
, shared_len
);
556 RARRAY_PTR_USE(ary
, ptr
, {
557 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
559 FL_SET_EMBED(shared_root
);
560 rb_ary_decrement_share(shared_root
);
563 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
564 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
566 ARY_SET_CAPA(ary
, len
);
567 ARY_SET_PTR(ary
, ptr
);
570 rb_gc_writebarrier_remember(ary
);
576 rb_ary_modify(VALUE ary
)
578 rb_ary_modify_check(ary
);
579 rb_ary_cancel_sharing(ary
);
583 ary_ensure_room_for_push(VALUE ary
, long add_len
)
585 long old_len
= RARRAY_LEN(ary
);
586 long new_len
= old_len
+ add_len
;
589 if (old_len
> ARY_MAX_SIZE
- add_len
) {
590 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
592 if (ARY_SHARED_P(ary
)) {
593 if (new_len
> ary_embed_capa(ary
)) {
594 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
595 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
596 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
597 rb_ary_modify_check(ary
);
600 ary_verify(shared_root
);
604 /* if array is shared, then it is likely it participate in push/shift pattern */
606 capa
= ARY_CAPA(ary
);
607 if (new_len
> capa
- (capa
>> 6)) {
608 ary_double_capa(ary
, new_len
);
619 rb_ary_modify_check(ary
);
621 capa
= ARY_CAPA(ary
);
622 if (new_len
> capa
) {
623 ary_double_capa(ary
, new_len
);
632 * array.freeze -> self
634 * Freezes +self+; returns +self+:
637 * a.frozen? # => false
639 * a.frozen? # => true
641 * An attempt to modify a frozen +Array+ raises FrozenError.
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
)
714 rb_raise(rb_eArgError
, "negative array size (or size too big)");
716 if (capa
> ARY_MAX_SIZE
) {
717 rb_raise(rb_eArgError
, "array size too big");
720 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
722 if (ary_embeddable_p(capa
)) {
723 ary
= ary_alloc_embed(klass
, capa
);
726 ary
= ary_alloc_heap(klass
);
727 ARY_SET_CAPA(ary
, capa
);
728 RUBY_ASSERT(!ARY_EMBED_P(ary
));
730 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
731 ARY_SET_HEAP_LEN(ary
, 0);
738 rb_ary_new_capa(long capa
)
740 return ary_new(rb_cArray
, capa
);
746 return rb_ary_new_capa(0);
750 (rb_ary_new_from_args
)(long n
, ...)
756 ary
= rb_ary_new2(n
);
759 for (i
=0; i
<n
; i
++) {
760 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
769 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
773 ary
= ary_new(klass
, n
);
775 ary_memcpy(ary
, 0, n
, elts
);
783 rb_ary_new_from_values(long n
, const VALUE
*elts
)
785 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
789 ec_ary_alloc_embed(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
791 size_t size
= ary_embed_size(capa
);
792 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
793 NEWOBJ_OF(ary
, struct RArray
, klass
,
794 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
797 * FL_SET_EMBED((VALUE)ary);
798 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
804 ec_ary_alloc_heap(rb_execution_context_t
*ec
, VALUE klass
)
806 NEWOBJ_OF(ary
, struct RArray
, klass
,
807 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
808 sizeof(struct RArray
), ec
);
813 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
818 rb_raise(rb_eArgError
, "negative array size (or size too big)");
820 if (capa
> ARY_MAX_SIZE
) {
821 rb_raise(rb_eArgError
, "array size too big");
824 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
826 if (ary_embeddable_p(capa
)) {
827 ary
= ec_ary_alloc_embed(ec
, klass
, capa
);
830 ary
= ec_ary_alloc_heap(ec
, klass
);
831 ARY_SET_CAPA(ary
, capa
);
832 RUBY_ASSERT(!ARY_EMBED_P(ary
));
834 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
835 ARY_SET_HEAP_LEN(ary
, 0);
842 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
846 ary
= ec_ary_new(ec
, rb_cArray
, n
);
848 ary_memcpy(ary
, 0, n
, elts
);
856 rb_ary_hidden_new(long capa
)
858 VALUE ary
= ary_new(0, capa
);
863 rb_ary_hidden_new_fill(long capa
)
865 VALUE ary
= rb_ary_hidden_new(capa
);
866 ary_memfill(ary
, 0, capa
, Qnil
);
867 ARY_SET_LEN(ary
, capa
);
872 rb_ary_free(VALUE ary
)
874 if (ARY_OWNS_HEAP_P(ary
)) {
875 if (USE_DEBUG_COUNTER
&&
876 !ARY_SHARED_ROOT_P(ary
) &&
877 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
878 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
881 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
885 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
888 if (ARY_SHARED_P(ary
)) {
889 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
891 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
892 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
896 static VALUE fake_ary_flags
;
899 init_fake_ary_flags(void)
901 struct RArray fake_ary
= {0};
902 fake_ary
.basic
.flags
= T_ARRAY
;
903 VALUE ary
= (VALUE
)&fake_ary
;
905 return fake_ary
.basic
.flags
;
909 rb_setup_fake_ary(struct RArray
*fake_ary
, const VALUE
*list
, long len
)
911 fake_ary
->basic
.flags
= fake_ary_flags
;
912 RBASIC_CLEAR_CLASS((VALUE
)fake_ary
);
914 // bypass frozen checks
915 fake_ary
->as
.heap
.ptr
= list
;
916 fake_ary
->as
.heap
.len
= len
;
917 fake_ary
->as
.heap
.aux
.capa
= len
;
918 return (VALUE
)fake_ary
;
922 rb_ary_memsize(VALUE ary
)
924 if (ARY_OWNS_HEAP_P(ary
)) {
925 return ARY_CAPA(ary
) * sizeof(VALUE
);
933 ary_make_shared(VALUE ary
)
937 if (ARY_SHARED_P(ary
)) {
938 return ARY_SHARED_ROOT(ary
);
940 else if (ARY_SHARED_ROOT_P(ary
)) {
943 else if (OBJ_FROZEN(ary
)) {
947 long capa
= ARY_CAPA(ary
);
948 long len
= RARRAY_LEN(ary
);
950 /* Shared roots cannot be embedded because the reference count
951 * (refcnt) is stored in as.heap.aux.capa. */
952 VALUE shared
= ary_alloc_heap(0);
953 FL_SET_SHARED_ROOT(shared
);
955 if (ARY_EMBED_P(ary
)) {
956 VALUE
*ptr
= ary_heap_alloc_buffer(capa
);
957 ARY_SET_PTR(shared
, ptr
);
958 ary_memcpy(shared
, 0, len
, RARRAY_CONST_PTR(ary
));
961 ARY_SET_HEAP_LEN(ary
, len
);
962 ARY_SET_PTR(ary
, ptr
);
965 ARY_SET_PTR(shared
, RARRAY_CONST_PTR(ary
));
968 ARY_SET_LEN(shared
, capa
);
969 ary_mem_clear(shared
, len
, capa
- len
);
970 rb_ary_set_shared(ary
, shared
);
980 ary_make_substitution(VALUE ary
)
982 long len
= RARRAY_LEN(ary
);
984 if (ary_embeddable_p(len
)) {
985 VALUE subst
= rb_ary_new_capa(len
);
986 RUBY_ASSERT(ARY_EMBED_P(subst
));
988 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR(ary
));
989 ARY_SET_EMBED_LEN(subst
, len
);
993 return rb_ary_increment_share(ary_make_shared(ary
));
998 rb_assoc_new(VALUE car
, VALUE cdr
)
1000 return rb_ary_new3(2, car
, cdr
);
1004 rb_to_array_type(VALUE ary
)
1006 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1008 #define to_ary rb_to_array_type
1011 rb_check_array_type(VALUE ary
)
1013 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1017 rb_check_to_array(VALUE ary
)
1019 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1023 rb_to_array(VALUE ary
)
1025 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1030 * Array.try_convert(object) -> object, new_array, or nil
1032 * Attempts to return an array, based on the given +object+.
1034 * If +object+ is an array, returns +object+.
1036 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1037 * calls <tt>object.to_ary</tt>:
1038 * if the return value is an array or +nil+, returns that value;
1039 * if not, raises TypeError.
1041 * Otherwise returns +nil+.
1043 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1047 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1049 return rb_check_array_type(ary
);
1054 rb_ary_s_new(int argc
, VALUE
*argv
, VALUE klass
)
1058 if (klass
== rb_cArray
) {
1060 if (argc
> 0 && FIXNUM_P(argv
[0])) {
1061 size
= FIX2LONG(argv
[0]);
1062 if (size
< 0) size
= 0;
1065 ary
= ary_new(klass
, size
);
1067 rb_obj_call_init_kw(ary
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
1070 ary
= rb_class_new_instance_pass_kw(argc
, argv
, klass
);
1078 * Array.new -> new_empty_array
1079 * Array.new(array) -> new_array
1080 * Array.new(size, default_value = nil) -> new_array
1081 * Array.new(size = 0) {|index| ... } -> new_array
1083 * Returns a new array.
1085 * With no block and no argument given, returns a new empty array:
1089 * With no block and array argument given, returns a new array with the same elements:
1091 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1093 * With no block and integer argument given, returns a new array containing
1094 * that many instances of the given +default_value+:
1096 * Array.new(0) # => []
1097 * Array.new(3) # => [nil, nil, nil]
1098 * Array.new(2, 3) # => [3, 3]
1100 * With a block given, returns an array of the given +size+;
1101 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1102 * the element at that +index+ in the returned array is the blocks return value:
1104 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1106 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1108 * array = Array.new(2, {})
1109 * array # => [{}, {}]
1111 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1113 * If you want the elements of the array to be distinct, you should pass a block:
1115 * array = Array.new(2) { {} }
1116 * array # => [{}, {}]
1118 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1120 * Raises TypeError if the first argument is not either an array
1121 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1122 * Raises ArgumentError if the first argument is a negative integer.
1124 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1128 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1136 RUBY_ASSERT(ARY_EMBED_P(ary
));
1137 RUBY_ASSERT(ARY_EMBED_LEN(ary
) == 0);
1138 if (rb_block_given_p()) {
1139 rb_warning("given block not used");
1143 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1144 if (argc
== 1 && !FIXNUM_P(size
)) {
1145 val
= rb_check_array_type(size
);
1147 rb_ary_replace(ary
, val
);
1152 len
= NUM2LONG(size
);
1153 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1155 rb_raise(rb_eArgError
, "negative array size");
1157 if (len
> ARY_MAX_SIZE
) {
1158 rb_raise(rb_eArgError
, "array size too big");
1160 /* recheck after argument conversion */
1162 ary_resize_capa(ary
, len
);
1163 if (rb_block_given_p()) {
1167 rb_warn("block supersedes default value argument");
1169 for (i
=0; i
<len
; i
++) {
1170 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1171 ARY_SET_LEN(ary
, i
+ 1);
1175 ary_memfill(ary
, 0, len
, val
);
1176 ARY_SET_LEN(ary
, len
);
1182 * Returns a new array, populated with the given objects:
1184 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1186 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1188 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1192 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1194 VALUE ary
= ary_new(klass
, argc
);
1195 if (argc
> 0 && argv
) {
1196 ary_memcpy(ary
, 0, argc
, argv
);
1197 ARY_SET_LEN(ary
, argc
);
1204 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1206 long len
= RARRAY_LEN(ary
);
1211 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1215 else if (idx
>= ARY_MAX_SIZE
) {
1216 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1220 if (idx
>= ARY_CAPA(ary
)) {
1221 ary_double_capa(ary
, idx
);
1224 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1228 ARY_SET_LEN(ary
, idx
+ 1);
1230 ARY_SET(ary
, idx
, val
);
1234 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1236 RUBY_ASSERT(offset
>= 0);
1237 RUBY_ASSERT(len
>= 0);
1238 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1240 VALUE result
= ary_alloc_heap(klass
);
1241 size_t embed_capa
= ary_embed_capa(result
);
1242 if ((size_t)len
<= embed_capa
) {
1243 FL_SET_EMBED(result
);
1244 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR(ary
) + offset
);
1245 ARY_SET_EMBED_LEN(result
, len
);
1248 VALUE shared
= ary_make_shared(ary
);
1250 /* The ary_make_shared call may allocate, which can trigger a GC
1251 * compaction. This can cause the array to be embedded because it has
1253 FL_UNSET_EMBED(result
);
1255 ARY_SET_PTR(result
, RARRAY_CONST_PTR(ary
));
1256 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1257 rb_ary_set_shared(result
, shared
);
1259 ARY_INCREASE_PTR(result
, offset
);
1260 ARY_SET_LEN(result
, len
);
1270 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1272 RUBY_ASSERT(offset
>= 0);
1273 RUBY_ASSERT(len
>= 0);
1274 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1275 RUBY_ASSERT(step
!= 0);
1277 const long orig_len
= len
;
1279 if (step
> 0 && step
>= len
) {
1280 VALUE result
= ary_new(klass
, 1);
1281 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1282 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1284 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1285 ARY_SET_EMBED_LEN(result
, 1);
1288 else if (step
< 0 && step
< -len
) {
1292 long ustep
= (step
< 0) ? -step
: step
;
1293 len
= roomof(len
, ustep
);
1296 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1298 VALUE result
= ary_new(klass
, len
);
1299 if (ARY_EMBED_P(result
)) {
1300 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1301 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1303 for (i
= 0; i
< len
; ++i
) {
1304 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1307 ARY_SET_EMBED_LEN(result
, len
);
1310 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1312 RARRAY_PTR_USE(result
, ptr
, {
1313 for (i
= 0; i
< len
; ++i
) {
1314 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1318 ARY_SET_LEN(result
, len
);
1325 ary_make_shared_copy(VALUE ary
)
1327 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1330 enum ary_take_pos_flags
1337 ary_take_first_or_last_n(VALUE ary
, long n
, enum ary_take_pos_flags last
)
1339 long len
= RARRAY_LEN(ary
);
1346 rb_raise(rb_eArgError
, "negative array size");
1351 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1355 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1357 argc
= rb_check_arity(argc
, 0, 1);
1358 /* the case optional argument is omitted should be handled in
1359 * callers of this function. if another arity case is added,
1360 * this arity check needs to rewrite. */
1361 RUBY_ASSERT_ALWAYS(argc
== 1);
1362 return ary_take_first_or_last_n(ary
, NUM2LONG(argv
[0]), last
);
1367 * self << object -> self
1369 * Appends +object+ as the last element in +self+; returns +self+:
1371 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1373 * Appends +object+ as a single element, even if it is another array:
1375 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1377 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1381 rb_ary_push(VALUE ary
, VALUE item
)
1383 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1384 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1385 RARRAY_PTR_USE(ary
, ptr
, {
1386 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1388 ARY_SET_LEN(ary
, idx
+ 1);
1394 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1396 long oldlen
= RARRAY_LEN(ary
);
1397 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1398 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1399 ARY_SET_LEN(ary
, oldlen
+ len
);
1405 * push(*objects) -> self
1406 * append(*objects) -> self
1408 * Appends each argument in +objects+ to +self+; returns +self+:
1410 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1411 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1413 * Appends each argument as a single element, even if it is another array:
1415 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1416 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1418 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1422 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1424 return rb_ary_cat(ary
, argv
, argc
);
1428 rb_ary_pop(VALUE ary
)
1431 rb_ary_modify_check(ary
);
1432 n
= RARRAY_LEN(ary
);
1433 if (n
== 0) return Qnil
;
1434 if (ARY_OWNS_HEAP_P(ary
) &&
1435 n
* 3 < ARY_CAPA(ary
) &&
1436 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1438 ary_resize_capa(ary
, n
* 2);
1441 ARY_SET_LEN(ary
, n
);
1443 return RARRAY_AREF(ary
, n
);
1448 * array.pop -> object or nil
1449 * array.pop(n) -> new_array
1451 * Removes and returns trailing elements.
1453 * When no argument is given and +self+ is not empty,
1454 * removes and returns the last element:
1456 * a = [:foo, 'bar', 2]
1458 * a # => [:foo, "bar"]
1460 * Returns +nil+ if the array is empty.
1462 * When a non-negative Integer argument +n+ is given and is in range,
1464 * removes and returns the last +n+ elements in a new +Array+:
1465 * a = [:foo, 'bar', 2]
1466 * a.pop(2) # => ["bar", 2]
1468 * If +n+ is positive and out of range,
1469 * removes and returns all elements:
1471 * a = [:foo, 'bar', 2]
1472 * a.pop(50) # => [:foo, "bar", 2]
1474 * Related: #push, #shift, #unshift.
1478 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1483 return rb_ary_pop(ary
);
1486 rb_ary_modify_check(ary
);
1487 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1488 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1494 rb_ary_shift(VALUE ary
)
1497 long len
= RARRAY_LEN(ary
);
1500 rb_ary_modify_check(ary
);
1504 top
= RARRAY_AREF(ary
, 0);
1506 rb_ary_behead(ary
, 1);
1513 * array.shift -> object or nil
1514 * array.shift(n) -> new_array
1516 * Removes and returns leading elements.
1518 * When no argument is given, removes and returns the first element:
1520 * a = [:foo, 'bar', 2]
1524 * Returns +nil+ if +self+ is empty.
1526 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1527 * returns those elements in a new +Array+:
1529 * a = [:foo, 'bar', 2]
1530 * a.shift(2) # => [:foo, 'bar']
1533 * If +n+ is as large as or larger than <tt>self.length</tt>,
1534 * removes all elements; returns those elements in a new +Array+:
1536 * a = [:foo, 'bar', 2]
1537 * a.shift(3) # => [:foo, 'bar', 2]
1539 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1541 * Related: #push, #pop, #unshift.
1545 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1551 return rb_ary_shift(ary
);
1554 rb_ary_modify_check(ary
);
1555 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1556 n
= RARRAY_LEN(result
);
1557 rb_ary_behead(ary
,n
);
1563 rb_ary_behead(VALUE ary
, long n
)
1569 rb_ary_modify_check(ary
);
1571 if (!ARY_SHARED_P(ary
)) {
1572 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1573 RARRAY_PTR_USE(ary
, ptr
, {
1574 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1575 }); /* WB: no new reference */
1576 ARY_INCREASE_LEN(ary
, -n
);
1581 ary_mem_clear(ary
, 0, n
);
1582 ary_make_shared(ary
);
1584 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1585 ary_mem_clear(ary
, 0, n
);
1588 ARY_INCREASE_PTR(ary
, n
);
1589 ARY_INCREASE_LEN(ary
, -n
);
1596 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1598 if (head
- sharedp
< argc
) {
1599 long room
= capa
- len
- argc
;
1602 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1603 head
= sharedp
+ argc
+ room
;
1605 ARY_SET_PTR(ary
, head
- argc
);
1606 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1609 return ARY_SHARED_ROOT(ary
);
1613 ary_modify_for_unshift(VALUE ary
, int argc
)
1615 long len
= RARRAY_LEN(ary
);
1616 long new_len
= len
+ argc
;
1618 const VALUE
*head
, *sharedp
;
1621 capa
= ARY_CAPA(ary
);
1622 if (capa
- (capa
>> 6) <= new_len
) {
1623 ary_double_capa(ary
, new_len
);
1626 /* use shared array for big "queues" */
1627 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1630 /* make a room for unshifted items */
1631 capa
= ARY_CAPA(ary
);
1632 ary_make_shared(ary
);
1634 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1635 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1639 RARRAY_PTR_USE(ary
, ptr
, {
1640 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1649 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1651 long len
= RARRAY_LEN(ary
);
1652 long new_len
= len
+ argc
;
1654 if (len
> ARY_MAX_SIZE
- argc
) {
1655 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1657 else if (! ARY_SHARED_P(ary
)) {
1658 return ary_modify_for_unshift(ary
, argc
);
1661 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1662 long capa
= RARRAY_LEN(shared_root
);
1664 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1665 return ary_modify_for_unshift(ary
, argc
);
1667 else if (new_len
> capa
) {
1668 return ary_modify_for_unshift(ary
, argc
);
1671 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1672 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1674 rb_ary_modify_check(ary
);
1675 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1682 * array.unshift(*objects) -> self
1684 * Prepends the given +objects+ to +self+:
1686 * a = [:foo, 'bar', 2]
1687 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1689 * Related: #push, #pop, #shift.
1693 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1695 long len
= RARRAY_LEN(ary
);
1699 rb_ary_modify_check(ary
);
1703 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1704 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1705 ARY_SET_LEN(ary
, len
+ argc
);
1710 rb_ary_unshift(VALUE ary
, VALUE item
)
1712 return rb_ary_unshift_m(1, &item
, ary
);
1715 /* faster version - use this if you don't need to treat negative offset */
1717 rb_ary_elt(VALUE ary
, long offset
)
1719 long len
= RARRAY_LEN(ary
);
1720 if (len
== 0) return Qnil
;
1721 if (offset
< 0 || len
<= offset
) {
1724 return RARRAY_AREF(ary
, offset
);
1728 rb_ary_entry(VALUE ary
, long offset
)
1730 return rb_ary_entry_internal(ary
, offset
);
1734 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1737 long alen
= RARRAY_LEN(ary
);
1739 if (beg
> alen
) return Qnil
;
1740 if (beg
< 0 || len
< 0) return Qnil
;
1742 if (alen
< len
|| alen
< beg
+ len
) {
1746 if (len
== 0) return ary_new(klass
, 0);
1748 rb_raise(rb_eArgError
, "slice step cannot be zero");
1750 return ary_make_partial(ary
, klass
, beg
, len
);
1752 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1756 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1758 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1761 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1765 * self[index] -> object or nil
1766 * self[start, length] -> object or nil
1767 * self[range] -> object or nil
1768 * self[aseq] -> object or nil
1769 * slice(index) -> object or nil
1770 * slice(start, length) -> object or nil
1771 * slice(range) -> object or nil
1772 * slice(aseq) -> object or nil
1774 * Returns elements from +self+; does not modify +self+.
1778 * a = [:foo, 'bar', 2]
1780 * # Single argument index: returns one element.
1781 * a[0] # => :foo # Zero-based index.
1782 * a[-1] # => 2 # Negative index counts backwards from end.
1784 * # Arguments start and length: returns an array.
1785 * a[1, 2] # => ["bar", 2]
1786 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1788 * # Single argument range: returns an array.
1789 * a[0..1] # => [:foo, "bar"]
1790 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1791 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1793 * When a single integer argument +index+ is given, returns the element at offset +index+:
1795 * a = [:foo, 'bar', 2]
1798 * a # => [:foo, "bar", 2]
1800 * If +index+ is negative, counts backwards from the end of +self+:
1802 * a = [:foo, 'bar', 2]
1806 * If +index+ is out of range, returns +nil+.
1808 * When two Integer arguments +start+ and +length+ are given,
1809 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1811 * a = [:foo, 'bar', 2]
1812 * a[0, 2] # => [:foo, "bar"]
1813 * a[1, 2] # => ["bar", 2]
1815 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1816 * returns all elements from offset +start+ to the end:
1818 * a = [:foo, 'bar', 2]
1819 * a[0, 4] # => [:foo, "bar", 2]
1820 * a[1, 3] # => ["bar", 2]
1823 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1824 * returns a new empty +Array+.
1826 * If +length+ is negative, returns +nil+.
1828 * When a single Range argument +range+ is given,
1829 * treats <tt>range.min</tt> as +start+ above
1830 * and <tt>range.size</tt> as +length+ above:
1832 * a = [:foo, 'bar', 2]
1833 * a[0..1] # => [:foo, "bar"]
1834 * a[1..2] # => ["bar", 2]
1836 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1838 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1840 * a = [:foo, 'bar', 2]
1841 * a[0..-1] # => [:foo, "bar", 2]
1842 * a[0..-2] # => [:foo, "bar"]
1843 * a[0..-3] # => [:foo]
1845 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1847 * a = [:foo, 'bar', 2]
1849 * a[-2..2] # => ["bar", 2]
1850 * a[-3..2] # => [:foo, "bar", 2]
1852 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1854 * a = [:foo, 'bar', 2]
1859 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1860 * returns an +Array+ of elements corresponding to the indexes produced by
1863 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1864 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1866 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1867 * is larger than array size, throws RangeError.
1869 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1870 * a[(1..11).step(2)]
1871 * # RangeError (((1..11).step(2)) out of range)
1873 * # RangeError (((7..).step(2)) out of range)
1875 * If given a single argument, and its type is not one of the listed, tries to
1876 * convert it to Integer, and raises if it is impossible:
1878 * a = [:foo, 'bar', 2]
1879 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1882 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1886 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1888 rb_check_arity(argc
, 1, 2);
1890 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1892 return rb_ary_aref1(ary
, argv
[0]);
1896 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1898 long beg
= NUM2LONG(b
);
1899 long len
= NUM2LONG(e
);
1901 beg
+= RARRAY_LEN(ary
);
1903 return rb_ary_subseq(ary
, beg
, len
);
1907 rb_ary_aref1(VALUE ary
, VALUE arg
)
1909 long beg
, len
, step
;
1911 /* special case - speeding up */
1912 if (FIXNUM_P(arg
)) {
1913 return rb_ary_entry(ary
, FIX2LONG(arg
));
1915 /* check if idx is Range or ArithmeticSequence */
1916 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1922 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1925 return rb_ary_entry(ary
, NUM2LONG(arg
));
1930 * at(index) -> object or nil
1932 * Returns the element of +self+ specified by the given +index+
1933 * or +nil+ if there is no such element;
1934 * +index+ must be an
1935 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1937 * For non-negative +index+, returns the element of +self+ at offset +index+:
1939 * a = [:foo, 'bar', 2]
1944 * For negative +index+, counts backwards from the end of +self+:
1946 * a.at(-2) # => "bar"
1948 * Related: Array#[];
1949 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1953 rb_ary_at(VALUE ary
, VALUE pos
)
1955 return rb_ary_entry(ary
, NUM2LONG(pos
));
1960 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1963 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1964 return RARRAY_AREF(ary
, 0);
1967 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1973 ary_first(VALUE self
)
1975 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1979 ary_last(VALUE self
)
1981 long len
= RARRAY_LEN(self
);
1982 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1986 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1989 return ary_last(ary
);
1992 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1998 * fetch(index) -> element
1999 * fetch(index, default_value) -> element or default_value
2000 * fetch(index) {|index| ... } -> element or block_return_value
2002 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2003 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2005 * With the single argument +index+ and no block,
2006 * returns the element at offset +index+:
2008 * a = [:foo, 'bar', 2]
2009 * a.fetch(1) # => "bar"
2010 * a.fetch(1.1) # => "bar"
2012 * If +index+ is negative, counts from the end of the array:
2014 * a = [:foo, 'bar', 2]
2015 * a.fetch(-1) # => 2
2016 * a.fetch(-2) # => "bar"
2018 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2019 * returns +default_value+ if +index+ is out-of-range:
2021 * a = [:foo, 'bar', 2]
2022 * a.fetch(1, nil) # => "bar"
2023 * a.fetch(3, :foo) # => :foo
2025 * With argument +index+ and a block,
2026 * returns the element at offset +index+ if index is in range
2027 * (and the block is not called); otherwise calls the block with index and returns its return value:
2029 * a = [:foo, 'bar', 2]
2030 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2031 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2033 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2037 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
2043 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
2044 block_given
= rb_block_given_p();
2045 if (block_given
&& argc
== 2) {
2046 rb_warn("block supersedes default value argument");
2048 idx
= NUM2LONG(pos
);
2051 idx
+= RARRAY_LEN(ary
);
2053 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2054 if (block_given
) return rb_yield(pos
);
2056 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2057 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2061 return RARRAY_AREF(ary
, idx
);
2066 * array.index(object) -> integer or nil
2067 * array.index {|element| ... } -> integer or nil
2068 * array.index -> new_enumerator
2070 * Returns the index of a specified element.
2072 * When argument +object+ is given but no block,
2073 * returns the index of the first element +element+
2074 * for which <tt>object == element</tt>:
2076 * a = [:foo, 'bar', 2, 'bar']
2077 * a.index('bar') # => 1
2079 * Returns +nil+ if no such element found.
2081 * When both argument +object+ and a block are given,
2082 * calls the block with each successive element;
2083 * returns the index of the first element for which the block returns a truthy value:
2085 * a = [:foo, 'bar', 2, 'bar']
2086 * a.index {|element| element == 'bar' } # => 1
2088 * Returns +nil+ if the block never returns a truthy value.
2090 * When neither an argument nor a block is given, returns a new Enumerator:
2092 * a = [:foo, 'bar', 2]
2094 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2095 * e.each {|element| element == 'bar' } # => 1
2101 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2107 RETURN_ENUMERATOR(ary
, 0, 0);
2108 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2109 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2115 rb_check_arity(argc
, 0, 1);
2117 if (rb_block_given_p())
2118 rb_warn("given block not used");
2119 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2120 VALUE e
= RARRAY_AREF(ary
, i
);
2121 if (rb_equal(e
, val
)) {
2130 * array.rindex(object) -> integer or nil
2131 * array.rindex {|element| ... } -> integer or nil
2132 * array.rindex -> new_enumerator
2134 * Returns the index of the last element for which <tt>object == element</tt>.
2136 * When argument +object+ is given but no block, returns the index of the last such element found:
2138 * a = [:foo, 'bar', 2, 'bar']
2139 * a.rindex('bar') # => 3
2141 * Returns +nil+ if no such object found.
2143 * When a block is given but no argument, calls the block with each successive element;
2144 * returns the index of the last element for which the block returns a truthy value:
2146 * a = [:foo, 'bar', 2, 'bar']
2147 * a.rindex {|element| element == 'bar' } # => 3
2149 * Returns +nil+ if the block never returns a truthy value.
2151 * When neither an argument nor a block is given, returns a new Enumerator:
2153 * a = [:foo, 'bar', 2, 'bar']
2155 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2156 * e.each {|element| element == 'bar' } # => 3
2162 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2165 long i
= RARRAY_LEN(ary
), len
;
2168 RETURN_ENUMERATOR(ary
, 0, 0);
2170 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2172 if (i
> (len
= RARRAY_LEN(ary
))) {
2178 rb_check_arity(argc
, 0, 1);
2180 if (rb_block_given_p())
2181 rb_warn("given block not used");
2183 VALUE e
= RARRAY_AREF(ary
, i
);
2184 if (rb_equal(e
, val
)) {
2187 if (i
> RARRAY_LEN(ary
)) {
2195 rb_ary_to_ary(VALUE obj
)
2197 VALUE tmp
= rb_check_array_type(obj
);
2199 if (!NIL_P(tmp
)) return tmp
;
2200 return rb_ary_new3(1, obj
);
2204 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2209 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2210 olen
= RARRAY_LEN(ary
);
2214 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2218 if (olen
< len
|| olen
< beg
+ len
) {
2223 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2224 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2229 if (beg
> ARY_MAX_SIZE
- rlen
) {
2230 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2232 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2234 ary_mem_clear(ary
, olen
, beg
- olen
);
2236 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2237 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2239 ARY_SET_LEN(ary
, len
);
2244 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2245 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2248 alen
= olen
+ rlen
- len
;
2249 if (alen
>= ARY_CAPA(ary
)) {
2250 ary_double_capa(ary
, alen
);
2254 RARRAY_PTR_USE(ary
, ptr
,
2255 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2256 VALUE
, olen
- (beg
+ len
)));
2257 ARY_SET_LEN(ary
, alen
);
2261 rb_gc_writebarrier_remember(ary
);
2264 /* In this case, we're copying from a region in this array, so
2265 * we don't need to fire the write barrier. */
2266 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2269 /* do not use RARRAY_PTR() because it can causes GC.
2270 * ary can contain T_NONE object because it is not cleared.
2272 RARRAY_PTR_USE(ary
, ptr
,
2273 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2279 rb_ary_set_len(VALUE ary
, long len
)
2283 rb_ary_modify_check(ary
);
2284 if (ARY_SHARED_P(ary
)) {
2285 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2287 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2288 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2290 ARY_SET_LEN(ary
, len
);
2294 rb_ary_resize(VALUE ary
, long len
)
2299 olen
= RARRAY_LEN(ary
);
2300 if (len
== olen
) return ary
;
2301 if (len
> ARY_MAX_SIZE
) {
2302 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2305 if (len
>= ARY_CAPA(ary
)) {
2306 ary_double_capa(ary
, len
);
2308 ary_mem_clear(ary
, olen
, len
- olen
);
2309 ARY_SET_LEN(ary
, len
);
2311 else if (ARY_EMBED_P(ary
)) {
2312 ARY_SET_EMBED_LEN(ary
, len
);
2314 else if (len
<= ary_embed_capa(ary
)) {
2315 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2316 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2317 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2321 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2322 ARY_SET_EMBED_LEN(ary
, len
);
2324 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2327 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2328 size_t new_capa
= ary_heap_realloc(ary
, len
);
2329 ARY_SET_CAPA(ary
, new_capa
);
2331 ARY_SET_HEAP_LEN(ary
, len
);
2338 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2340 rb_ary_store(ary
, key
, val
);
2345 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2347 VALUE rpl
= rb_ary_to_ary(val
);
2348 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2355 * self[index] = object -> object
2356 * self[start, length] = object -> object
2357 * self[range] = object -> object
2359 * Assigns elements in +self+, based on the given +object+; returns +object+.
2363 * a_orig = [:foo, 'bar', 2]
2365 * # With argument index.
2367 * a[0] = 'foo' # => "foo"
2368 * a # => ["foo", "bar", 2]
2370 * a[7] = 'foo' # => "foo"
2371 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2373 * # With arguments start and length.
2375 * a[0, 2] = 'foo' # => "foo"
2378 * a[6, 50] = 'foo' # => "foo"
2379 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2381 * # With argument range.
2383 * a[0..1] = 'foo' # => "foo"
2386 * a[6..50] = 'foo' # => "foo"
2387 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2389 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2391 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2393 * a = [:foo, 'bar', 2]
2394 * a[0] = 'foo' # => "foo"
2395 * a # => ["foo", "bar", 2]
2397 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2399 * a = [:foo, 'bar', 2]
2400 * a[7] = 'foo' # => "foo"
2401 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2403 * If +index+ is negative, counts backwards from the end of the array:
2405 * a = [:foo, 'bar', 2]
2406 * a[-1] = 'two' # => "two"
2407 * a # => [:foo, "bar", "two"]
2409 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2410 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2411 * and assigns +object+ at offset +start+:
2413 * a = [:foo, 'bar', 2]
2414 * a[0, 2] = 'foo' # => "foo"
2417 * If +start+ is negative, counts backwards from the end of the array:
2419 * a = [:foo, 'bar', 2]
2420 * a[-2, 2] = 'foo' # => "foo"
2421 * a # => [:foo, "foo"]
2423 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2424 * extends the array with +nil+, assigns +object+ at offset +start+,
2425 * and ignores +length+:
2427 * a = [:foo, 'bar', 2]
2428 * a[6, 50] = 'foo' # => "foo"
2429 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2431 * If +length+ is zero, shifts elements at and following offset +start+
2432 * and assigns +object+ at offset +start+:
2434 * a = [:foo, 'bar', 2]
2435 * a[1, 0] = 'foo' # => "foo"
2436 * a # => [:foo, "foo", "bar", 2]
2438 * If +length+ is too large for the existing array, does not extend the array:
2440 * a = [:foo, 'bar', 2]
2441 * a[1, 5] = 'foo' # => "foo"
2442 * a # => [:foo, "foo"]
2444 * When Range argument +range+ is given and +object+ is not an +Array+,
2445 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2446 * and assigns +object+ at offset +start+:
2448 * a = [:foo, 'bar', 2]
2449 * a[0..1] = 'foo' # => "foo"
2452 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2454 * a = [:foo, 'bar', 2]
2455 * a[-2..2] = 'foo' # => "foo"
2456 * a # => [:foo, "foo"]
2458 * If the array length is less than <tt>range.begin</tt>,
2459 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2460 * and ignores +length+:
2462 * a = [:foo, 'bar', 2]
2463 * a[6..50] = 'foo' # => "foo"
2464 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2466 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2467 * and assigns +object+ at offset +start+:
2469 * a = [:foo, 'bar', 2]
2470 * a[1..0] = 'foo' # => "foo"
2471 * a # => [:foo, "foo", "bar", 2]
2473 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2474 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2476 * a = [:foo, 'bar', 2]
2477 * a[1..-1] = 'foo' # => "foo"
2478 * a # => [:foo, "foo"]
2479 * a = [:foo, 'bar', 2]
2480 * a[1..-2] = 'foo' # => "foo"
2481 * a # => [:foo, "foo", 2]
2482 * a = [:foo, 'bar', 2]
2483 * a[1..-3] = 'foo' # => "foo"
2484 * a # => [:foo, "foo", "bar", 2]
2485 * a = [:foo, 'bar', 2]
2487 * If <tt>range.end</tt> is too large for the existing array,
2488 * replaces array elements, but does not extend the array with +nil+ values:
2490 * a = [:foo, 'bar', 2]
2491 * a[1..5] = 'foo' # => "foo"
2492 * a # => [:foo, "foo"]
2494 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2498 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2500 long offset
, beg
, len
;
2502 rb_check_arity(argc
, 2, 3);
2503 rb_ary_modify_check(ary
);
2505 beg
= NUM2LONG(argv
[0]);
2506 len
= NUM2LONG(argv
[1]);
2507 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2509 if (FIXNUM_P(argv
[0])) {
2510 offset
= FIX2LONG(argv
[0]);
2511 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2513 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2514 /* check if idx is Range */
2515 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2518 offset
= NUM2LONG(argv
[0]);
2519 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2524 * array.insert(index, *objects) -> self
2526 * Inserts given +objects+ before or after the element at Integer index +offset+;
2529 * When +index+ is non-negative, inserts all given +objects+
2530 * before the element at offset +index+:
2532 * a = [:foo, 'bar', 2]
2533 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2535 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2537 * a = [:foo, 'bar', 2]
2538 * a.insert(5, :bat, :bam)
2539 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2541 * Does nothing if no objects given:
2543 * a = [:foo, 'bar', 2]
2547 * a # => [:foo, "bar", 2]
2549 * When +index+ is negative, inserts all given +objects+
2550 * _after_ the element at offset <tt>index+self.size</tt>:
2552 * a = [:foo, 'bar', 2]
2553 * a.insert(-2, :bat, :bam)
2554 * a # => [:foo, "bar", :bat, :bam, 2]
2559 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2563 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2564 rb_ary_modify_check(ary
);
2565 pos
= NUM2LONG(argv
[0]);
2566 if (argc
== 1) return ary
;
2568 pos
= RARRAY_LEN(ary
);
2571 long minpos
= -RARRAY_LEN(ary
) - 1;
2573 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2578 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2583 rb_ary_length(VALUE ary
);
2586 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2588 return rb_ary_length(ary
);
2591 // Primitive to avoid a race condition in Array#each.
2592 // Return `true` and write `value` and `index` if the element exists.
2594 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2596 long i
= NUM2LONG(*index
);
2597 if (i
>= RARRAY_LEN(self
)) {
2600 *value
= RARRAY_AREF(self
, i
);
2601 *index
= LONG2NUM(i
+ 1);
2606 rb_ary_each(VALUE ary
)
2610 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2611 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2612 rb_yield(RARRAY_AREF(ary
, i
));
2619 * each_index {|index| ... } -> self
2620 * each_index -> new_enumerator
2622 * With a block given, iterates over the elements of +self+,
2623 * passing each <i>array index</i> to the block;
2626 * a = [:foo, 'bar', 2]
2627 * a.each_index {|index| puts "#{index} #{a[index]}" }
2635 * Allows the array to be modified during iteration:
2637 * a = [:foo, 'bar', 2]
2638 * a.each_index {|index| puts index; a.clear if index > 0 }
2645 * With no block given, returns a new Enumerator.
2647 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2651 rb_ary_each_index(VALUE ary
)
2654 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2656 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2657 rb_yield(LONG2NUM(i
));
2664 * array.reverse_each {|element| ... } -> self
2665 * array.reverse_each -> Enumerator
2667 * Iterates backwards over array elements.
2669 * When a block given, passes, in reverse order, each element to the block;
2672 * a = [:foo, 'bar', 2]
2673 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2681 * Allows the array to be modified during iteration:
2683 * a = [:foo, 'bar', 2]
2684 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2691 * When no block given, returns a new Enumerator:
2693 * a = [:foo, 'bar', 2]
2694 * e = a.reverse_each
2695 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2696 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2704 * Related: #each, #each_index.
2708 rb_ary_reverse_each(VALUE ary
)
2712 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2713 len
= RARRAY_LEN(ary
);
2716 rb_yield(RARRAY_AREF(ary
, len
));
2717 nlen
= RARRAY_LEN(ary
);
2727 * array.length -> an_integer
2729 * Returns the count of elements in +self+.
2733 rb_ary_length(VALUE ary
)
2735 long len
= RARRAY_LEN(ary
);
2736 return LONG2NUM(len
);
2741 * array.empty? -> true or false
2743 * Returns +true+ if the count of elements in +self+ is zero,
2744 * +false+ otherwise.
2746 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2750 rb_ary_empty_p(VALUE ary
)
2752 return RBOOL(RARRAY_LEN(ary
) == 0);
2756 rb_ary_dup(VALUE ary
)
2758 long len
= RARRAY_LEN(ary
);
2759 VALUE dup
= rb_ary_new2(len
);
2760 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2761 ARY_SET_LEN(dup
, len
);
2769 rb_ary_resurrect(VALUE ary
)
2771 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2774 extern VALUE rb_output_fs
;
2776 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2779 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2781 VALUE
*arg
= (VALUE
*)argp
;
2784 VALUE result
= arg
[2];
2785 int *first
= (int *)arg
[3];
2788 rb_raise(rb_eArgError
, "recursive array join");
2791 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2797 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2802 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2803 for (i
=0; i
<max
; i
++) {
2804 val
= RARRAY_AREF(ary
, i
);
2805 if (!RB_TYPE_P(val
, T_STRING
)) break;
2806 if (i
> 0 && !NIL_P(sep
))
2807 rb_str_buf_append(result
, sep
);
2808 rb_str_buf_append(result
, val
);
2814 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2816 rb_str_buf_append(dst
, src
);
2818 rb_enc_copy(dst
, src
);
2824 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2827 rb_raise(rb_eArgError
, "recursive array join");
2836 args
[3] = (VALUE
)first
;
2837 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2842 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2846 for (; i
<RARRAY_LEN(ary
); i
++) {
2847 if (i
> 0 && !NIL_P(sep
))
2848 rb_str_buf_append(result
, sep
);
2850 val
= RARRAY_AREF(ary
, i
);
2851 if (RB_TYPE_P(val
, T_STRING
)) {
2852 ary_join_1_str(result
, val
, first
);
2854 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2855 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2857 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2858 ary_join_1_str(result
, tmp
, first
);
2860 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2861 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2864 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2870 rb_ary_join(VALUE ary
, VALUE sep
)
2873 VALUE val
, tmp
, result
;
2875 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2879 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2881 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2882 val
= RARRAY_AREF(ary
, i
);
2883 tmp
= rb_check_string_type(val
);
2885 if (NIL_P(tmp
) || tmp
!= val
) {
2887 long n
= RARRAY_LEN(ary
);
2889 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2890 rb_enc_associate(result
, rb_usascii_encoding());
2891 i
= ary_join_0(ary
, sep
, i
, result
);
2893 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2897 len
+= RSTRING_LEN(tmp
);
2900 result
= rb_str_new(0, len
);
2901 rb_str_set_len(result
, 0);
2903 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2910 * array.join ->new_string
2911 * array.join(separator = $,) -> new_string
2913 * Returns the new String formed by joining the array elements after conversion.
2914 * For each element +element+:
2916 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2917 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2919 * With no argument, joins using the output field separator, <tt>$,</tt>:
2921 * a = [:foo, 'bar', 2]
2923 * a.join # => "foobar2"
2925 * With \string argument +separator+, joins using that separator:
2927 * a = [:foo, 'bar', 2]
2928 * a.join("\n") # => "foo\nbar\n2"
2930 * Joins recursively for nested Arrays:
2932 * a = [:foo, [:bar, [:baz, :bat]]]
2933 * a.join # => "foobarbazbat"
2937 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2941 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2944 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2948 return rb_ary_join(ary
, sep
);
2952 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2957 if (recur
) return rb_usascii_str_new_cstr("[...]");
2958 str
= rb_str_buf_new2("[");
2959 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2960 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2961 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2962 else rb_enc_copy(str
, s
);
2963 rb_str_buf_append(str
, s
);
2965 rb_str_buf_cat2(str
, "]");
2971 * array.inspect -> new_string
2973 * Returns the new String formed by calling method <tt>#inspect</tt>
2974 * on each array element:
2976 * a = [:foo, 'bar', 2]
2977 * a.inspect # => "[:foo, \"bar\", 2]"
2982 rb_ary_inspect(VALUE ary
)
2984 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
2985 return rb_exec_recursive(inspect_ary
, ary
, 0);
2989 rb_ary_to_s(VALUE ary
)
2991 return rb_ary_inspect(ary
);
2996 * to_a -> self or new_array
2998 * When +self+ is an instance of +Array+, returns +self+:
3000 * a = [:foo, 'bar', 2]
3001 * a.to_a # => [:foo, "bar", 2]
3003 * Otherwise, returns a new +Array+ containing the elements of +self+:
3005 * class MyArray < Array; end
3006 * a = MyArray.new(['foo', 'bar', 'two'])
3007 * a.instance_of?(Array) # => false
3008 * a.kind_of?(Array) # => true
3010 * a1 # => ["foo", "bar", "two"]
3011 * a1.class # => Array # Not MyArray
3016 rb_ary_to_a(VALUE ary
)
3018 if (rb_obj_class(ary
) != rb_cArray
) {
3019 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
3020 rb_ary_replace(dup
, ary
);
3028 * array.to_h -> new_hash
3029 * array.to_h {|item| ... } -> new_hash
3031 * Returns a new Hash formed from +self+.
3033 * When a block is given, calls the block with each array element;
3034 * the block must return a 2-element +Array+ whose two elements
3035 * form a key-value pair in the returned Hash:
3037 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3038 * h = a.to_h {|item| [item, item] }
3039 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
3041 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
3042 * each sub-array is formed into a key-value pair in the new Hash:
3045 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3047 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3052 rb_ary_to_h(VALUE ary
)
3055 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
3056 int block_given
= rb_block_given_p();
3058 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3059 const VALUE e
= rb_ary_elt(ary
, i
);
3060 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3061 const VALUE key_value_pair
= rb_check_array_type(elt
);
3062 if (NIL_P(key_value_pair
)) {
3063 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3064 rb_obj_class(elt
), i
);
3066 if (RARRAY_LEN(key_value_pair
) != 2) {
3067 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3068 i
, RARRAY_LEN(key_value_pair
));
3070 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3077 * array.to_ary -> self
3083 rb_ary_to_ary_m(VALUE ary
)
3089 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3099 rb_ary_reverse(VALUE ary
)
3102 long len
= RARRAY_LEN(ary
);
3106 RARRAY_PTR_USE(ary
, p1
, {
3107 p2
= p1
+ len
- 1; /* points last item */
3108 ary_reverse(p1
, p2
);
3109 }); /* WB: no new reference */
3116 * array.reverse! -> self
3118 * Reverses +self+ in place:
3120 * a = ['foo', 'bar', 'two']
3121 * a.reverse! # => ["two", "bar", "foo"]
3126 rb_ary_reverse_bang(VALUE ary
)
3128 return rb_ary_reverse(ary
);
3133 * array.reverse -> new_array
3135 * Returns a new +Array+ with the elements of +self+ in reverse order:
3137 * a = ['foo', 'bar', 'two']
3139 * a1 # => ["two", "bar", "foo"]
3144 rb_ary_reverse_m(VALUE ary
)
3146 long len
= RARRAY_LEN(ary
);
3147 VALUE dup
= rb_ary_new2(len
);
3150 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3151 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3152 do *p2
-- = *p1
++; while (--len
> 0);
3154 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3159 rotate_count(long cnt
, long len
)
3161 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3165 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3169 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3170 *(ptr
+ len
- 1) = tmp
;
3172 else if (cnt
== len
- 1) {
3173 VALUE tmp
= *(ptr
+ len
- 1);
3174 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3179 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3180 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3181 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3186 rb_ary_rotate(VALUE ary
, long cnt
)
3191 long len
= RARRAY_LEN(ary
);
3192 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3193 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3202 * array.rotate! -> self
3203 * array.rotate!(count) -> self
3205 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3207 * When no argument given, rotates the first element to the last position:
3209 * a = [:foo, 'bar', 2, 'bar']
3210 * a.rotate! # => ["bar", 2, "bar", :foo]
3212 * When given a non-negative Integer +count+,
3213 * rotates +count+ elements from the beginning to the end:
3215 * a = [:foo, 'bar', 2]
3217 * a # => [2, :foo, "bar"]
3219 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3221 * a = [:foo, 'bar', 2]
3223 * a # => [2, :foo, "bar"]
3225 * If +count+ is zero, returns +self+ unmodified:
3227 * a = [:foo, 'bar', 2]
3229 * a # => [:foo, "bar", 2]
3231 * When given a negative Integer +count+, rotates in the opposite direction,
3232 * from end to beginning:
3234 * a = [:foo, 'bar', 2]
3236 * a # => ["bar", 2, :foo]
3238 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3240 * a = [:foo, 'bar', 2]
3242 * a # => ["bar", 2, :foo]
3247 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3249 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3250 rb_ary_rotate(ary
, n
);
3256 * array.rotate -> new_array
3257 * array.rotate(count) -> new_array
3259 * Returns a new +Array+ formed from +self+ with elements
3260 * rotated from one end to the other.
3262 * When no argument given, returns a new +Array+ that is like +self+,
3263 * except that the first element has been rotated to the last position:
3265 * a = [:foo, 'bar', 2, 'bar']
3267 * a1 # => ["bar", 2, "bar", :foo]
3269 * When given a non-negative Integer +count+,
3270 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3272 * a = [:foo, 'bar', 2]
3274 * a1 # => [2, :foo, "bar"]
3276 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3278 * a = [:foo, 'bar', 2]
3280 * a1 # => [2, :foo, "bar"]
3282 * If +count+ is zero, returns a copy of +self+, unmodified:
3284 * a = [:foo, 'bar', 2]
3286 * a1 # => [:foo, "bar", 2]
3288 * When given a negative Integer +count+, rotates in the opposite direction,
3289 * from end to beginning:
3291 * a = [:foo, 'bar', 2]
3293 * a1 # => ["bar", 2, :foo]
3295 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3297 * a = [:foo, 'bar', 2]
3299 * a1 # => ["bar", 2, :foo]
3304 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3309 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3311 len
= RARRAY_LEN(ary
);
3312 rotated
= rb_ary_new2(len
);
3314 cnt
= rotate_count(cnt
, len
);
3315 ptr
= RARRAY_CONST_PTR(ary
);
3317 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3318 ary_memcpy(rotated
, len
, cnt
, ptr
);
3320 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3324 struct ary_sort_data
{
3330 sort_reentered(VALUE ary
)
3332 if (RBASIC(ary
)->klass
) {
3333 rb_raise(rb_eRuntimeError
, "sort reentered");
3339 sort_returned(struct ary_sort_data
*data
)
3341 if (rb_obj_frozen_p(data
->receiver
)) {
3342 rb_raise(rb_eFrozenError
, "array frozen during sort");
3344 sort_reentered(data
->ary
);
3348 sort_1(const void *ap
, const void *bp
, void *dummy
)
3350 struct ary_sort_data
*data
= dummy
;
3351 VALUE retval
= sort_reentered(data
->ary
);
3352 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3358 retval
= rb_yield_values2(2, args
);
3359 n
= rb_cmpint(retval
, a
, b
);
3360 sort_returned(data
);
3365 sort_2(const void *ap
, const void *bp
, void *dummy
)
3367 struct ary_sort_data
*data
= dummy
;
3368 VALUE retval
= sort_reentered(data
->ary
);
3369 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3372 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3373 if ((long)a
> (long)b
) return 1;
3374 if ((long)a
< (long)b
) return -1;
3377 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3378 return rb_str_cmp(a
, b
);
3380 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3381 return rb_float_cmp(a
, b
);
3384 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3385 n
= rb_cmpint(retval
, a
, b
);
3386 sort_returned(data
);
3393 * array.sort! -> self
3394 * array.sort! {|a, b| ... } -> self
3396 * Returns +self+ with its elements sorted in place.
3398 * With no block, compares elements using operator <tt><=></tt>
3401 * a = 'abcde'.split('').shuffle
3402 * a # => ["e", "b", "d", "a", "c"]
3404 * a # => ["a", "b", "c", "d", "e"]
3406 * With a block, calls the block with each element pair;
3407 * for each element pair +a+ and +b+, the block should return an integer:
3409 * - Negative when +b+ is to follow +a+.
3410 * - Zero when +a+ and +b+ are equivalent.
3411 * - Positive when +a+ is to follow +b+.
3415 * a = 'abcde'.split('').shuffle
3416 * a # => ["e", "b", "d", "a", "c"]
3417 * a.sort! {|a, b| a <=> b }
3418 * a # => ["a", "b", "c", "d", "e"]
3419 * a.sort! {|a, b| b <=> a }
3420 * a # => ["e", "d", "c", "b", "a"]
3422 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3423 * and may be unstable:
3425 * a = 'abcde'.split('').shuffle
3426 * a # => ["e", "b", "d", "a", "c"]
3427 * a.sort! {|a, b| 0 }
3428 * a # => ["d", "e", "c", "a", "b"]
3433 rb_ary_sort_bang(VALUE ary
)
3436 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3437 if (RARRAY_LEN(ary
) > 1) {
3438 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3439 struct ary_sort_data data
;
3440 long len
= RARRAY_LEN(ary
);
3441 RBASIC_CLEAR_CLASS(tmp
);
3443 data
.receiver
= ary
;
3444 RARRAY_PTR_USE(tmp
, ptr
, {
3445 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3446 rb_block_given_p()?sort_1
:sort_2
, &data
);
3447 }); /* WB: no new reference */
3449 if (ARY_EMBED_P(tmp
)) {
3450 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3451 rb_ary_unshare(ary
);
3454 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3455 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3457 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3458 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3461 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3462 FL_UNSET_SHARED(ary
);
3463 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3466 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3467 if (ARY_EMBED_P(ary
)) {
3468 FL_UNSET_EMBED(ary
);
3470 else if (ARY_SHARED_P(ary
)) {
3471 /* ary might be destructively operated in the given block */
3472 rb_ary_unshare(ary
);
3477 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3478 ARY_SET_HEAP_LEN(ary
, len
);
3479 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3481 /* tmp was lost ownership for the ptr */
3482 FL_UNSET(tmp
, FL_FREEZE
);
3484 ARY_SET_EMBED_LEN(tmp
, 0);
3485 FL_SET(tmp
, FL_FREEZE
);
3487 /* tmp will be GC'ed. */
3488 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3496 * array.sort -> new_array
3497 * array.sort {|a, b| ... } -> new_array
3499 * Returns a new +Array+ whose elements are those from +self+, sorted.
3501 * With no block, compares elements using operator <tt><=></tt>
3504 * a = 'abcde'.split('').shuffle
3505 * a # => ["e", "b", "d", "a", "c"]
3507 * a1 # => ["a", "b", "c", "d", "e"]
3509 * With a block, calls the block with each element pair;
3510 * for each element pair +a+ and +b+, the block should return an integer:
3512 * - Negative when +b+ is to follow +a+.
3513 * - Zero when +a+ and +b+ are equivalent.
3514 * - Positive when +a+ is to follow +b+.
3518 * a = 'abcde'.split('').shuffle
3519 * a # => ["e", "b", "d", "a", "c"]
3520 * a1 = a.sort {|a, b| a <=> b }
3521 * a1 # => ["a", "b", "c", "d", "e"]
3522 * a2 = a.sort {|a, b| b <=> a }
3523 * a2 # => ["e", "d", "c", "b", "a"]
3525 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3526 * and may be unstable:
3528 * a = 'abcde'.split('').shuffle
3529 * a # => ["e", "b", "d", "a", "c"]
3530 * a1 = a.sort {|a, b| 0 }
3531 * a1 # => ["c", "e", "b", "d", "a"]
3533 * Related: Enumerable#sort_by.
3537 rb_ary_sort(VALUE ary
)
3539 ary
= rb_ary_dup(ary
);
3540 rb_ary_sort_bang(ary
);
3544 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3548 * bsearch {|element| ... } -> found_element or nil
3549 * bsearch -> new_enumerator
3551 * Returns the element from +self+ found by a binary search,
3552 * or +nil+ if the search found no suitable element.
3554 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3556 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3560 rb_ary_bsearch(VALUE ary
)
3562 VALUE index_result
= rb_ary_bsearch_index(ary
);
3564 if (FIXNUM_P(index_result
)) {
3565 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3567 return index_result
;
3572 * bsearch_index {|element| ... } -> integer or nil
3573 * bsearch_index -> new_enumerator
3575 * Returns the integer index of the element from +self+ found by a binary search,
3576 * or +nil+ if the search found no suitable element.
3578 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3580 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3584 rb_ary_bsearch_index(VALUE ary
)
3586 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3587 int smaller
= 0, satisfied
= 0;
3590 RETURN_ENUMERATOR(ary
, 0, 0);
3591 while (low
< high
) {
3592 mid
= low
+ ((high
- low
) / 2);
3593 val
= rb_ary_entry(ary
, mid
);
3596 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3597 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3599 else if (v
== Qtrue
) {
3603 else if (!RTEST(v
)) {
3606 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3607 const VALUE zero
= INT2FIX(0);
3608 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3609 case 0: return INT2FIX(mid
);
3610 case 1: smaller
= 0; break;
3611 case -1: smaller
= 1;
3615 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3616 " (must be numeric, true, false or nil)",
3626 if (!satisfied
) return Qnil
;
3627 return INT2FIX(low
);
3632 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3639 * array.sort_by! {|element| ... } -> self
3640 * array.sort_by! -> new_enumerator
3642 * Sorts the elements of +self+ in place,
3643 * using an ordering determined by the block; returns self.
3645 * Calls the block with each successive element;
3646 * sorts elements based on the values returned from the block.
3648 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3650 * This example sorts strings based on their sizes:
3652 * a = ['aaaa', 'bbb', 'cc', 'd']
3653 * a.sort_by! {|element| element.size }
3654 * a # => ["d", "cc", "bbb", "aaaa"]
3656 * Returns a new Enumerator if no block given:
3658 * a = ['aaaa', 'bbb', 'cc', 'd']
3659 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3664 rb_ary_sort_by_bang(VALUE ary
)
3668 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3670 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3671 rb_ary_replace(ary
, sorted
);
3678 * collect {|element| ... } -> new_array
3679 * collect -> new_enumerator
3680 * map {|element| ... } -> new_array
3681 * map -> new_enumerator
3683 * With a block given, calls the block with each element of +self+;
3684 * returns a new array whose elements are the return values from the block:
3686 * a = [:foo, 'bar', 2]
3687 * a1 = a.map {|element| element.class }
3688 * a1 # => [Symbol, String, Integer]
3690 * With no block given, returns a new Enumerator.
3692 * Related: #collect!;
3693 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3697 rb_ary_collect(VALUE ary
)
3702 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3703 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3704 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3705 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3713 * collect! {|element| ... } -> new_array
3714 * collect! -> new_enumerator
3715 * map! {|element| ... } -> new_array
3716 * map! -> new_enumerator
3718 * With a block given, calls the block with each element of +self+
3719 * and replaces the element with the block's return value;
3722 * a = [:foo, 'bar', 2]
3723 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3725 * With no block given, returns a new Enumerator.
3727 * Related: #collect;
3728 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3732 rb_ary_collect_bang(VALUE ary
)
3736 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3738 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3739 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3745 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3747 VALUE result
= rb_ary_new2(argc
);
3748 long beg
, len
, i
, j
;
3750 for (i
=0; i
<argc
; i
++) {
3751 if (FIXNUM_P(argv
[i
])) {
3752 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3755 /* check if idx is Range */
3756 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3757 long end
= olen
< beg
+len
? olen
: beg
+len
;
3758 for (j
= beg
; j
< end
; j
++) {
3759 rb_ary_push(result
, (*func
)(obj
, j
));
3762 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3765 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3771 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3774 if (FIXNUM_P(idx
)) {
3775 beg
= FIX2LONG(idx
);
3777 /* check if idx is Range */
3778 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3780 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3781 const long end
= beg
+ len
;
3782 const long prevlen
= RARRAY_LEN(result
);
3784 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3787 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3793 beg
= NUM2LONG(idx
);
3795 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3800 * array.values_at(*indexes) -> new_array
3802 * Returns a new +Array+ whose elements are the elements
3803 * of +self+ at the given Integer or Range +indexes+.
3805 * For each positive +index+, returns the element at offset +index+:
3807 * a = [:foo, 'bar', 2]
3808 * a.values_at(0, 2) # => [:foo, 2]
3809 * a.values_at(0..1) # => [:foo, "bar"]
3811 * The given +indexes+ may be in any order, and may repeat:
3813 * a = [:foo, 'bar', 2]
3814 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3815 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3817 * Assigns +nil+ for an +index+ that is too large:
3819 * a = [:foo, 'bar', 2]
3820 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3822 * Returns a new empty +Array+ if no arguments given.
3824 * For each negative +index+, counts backward from the end of the array:
3826 * a = [:foo, 'bar', 2]
3827 * a.values_at(-1, -3) # => [2, :foo]
3829 * Assigns +nil+ for an +index+ that is too small:
3831 * a = [:foo, 'bar', 2]
3832 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3834 * The given +indexes+ may have a mixture of signs:
3836 * a = [:foo, 'bar', 2]
3837 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3842 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3844 long i
, olen
= RARRAY_LEN(ary
);
3845 VALUE result
= rb_ary_new_capa(argc
);
3846 for (i
= 0; i
< argc
; ++i
) {
3847 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3856 * array.select {|element| ... } -> new_array
3857 * array.select -> new_enumerator
3859 * Calls the block, if given, with each element of +self+;
3860 * returns a new +Array+ containing those elements of +self+
3861 * for which the block returns a truthy value:
3863 * a = [:foo, 'bar', 2, :bam]
3864 * a1 = a.select {|element| element.to_s.start_with?('b') }
3865 * a1 # => ["bar", :bam]
3867 * Returns a new Enumerator if no block given:
3869 * a = [:foo, 'bar', 2, :bam]
3870 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3875 rb_ary_select(VALUE ary
)
3880 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3881 result
= rb_ary_new2(RARRAY_LEN(ary
));
3882 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3883 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3884 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3890 struct select_bang_arg
{
3896 select_bang_i(VALUE a
)
3898 volatile struct select_bang_arg
*arg
= (void *)a
;
3899 VALUE ary
= arg
->ary
;
3902 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3903 VALUE v
= RARRAY_AREF(ary
, i1
);
3904 if (!RTEST(rb_yield(v
))) continue;
3906 rb_ary_store(ary
, i2
, v
);
3910 return (i1
== i2
) ? Qnil
: ary
;
3914 select_bang_ensure(VALUE a
)
3916 volatile struct select_bang_arg
*arg
= (void *)a
;
3917 VALUE ary
= arg
->ary
;
3918 long len
= RARRAY_LEN(ary
);
3919 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3921 if (i2
< len
&& i2
< i1
) {
3926 RARRAY_PTR_USE(ary
, ptr
, {
3927 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3930 ARY_SET_LEN(ary
, i2
+ tail
);
3937 * array.select! {|element| ... } -> self or nil
3938 * array.select! -> new_enumerator
3940 * Calls the block, if given with each element of +self+;
3941 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3943 * Returns +self+ if any elements were removed:
3945 * a = [:foo, 'bar', 2, :bam]
3946 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3948 * Returns +nil+ if no elements were removed.
3950 * Returns a new Enumerator if no block given:
3952 * a = [:foo, 'bar', 2, :bam]
3953 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3958 rb_ary_select_bang(VALUE ary
)
3960 struct select_bang_arg args
;
3962 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3966 args
.len
[0] = args
.len
[1] = 0;
3967 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3972 * array.keep_if {|element| ... } -> self
3973 * array.keep_if -> new_enumeration
3975 * Retains those elements for which the block returns a truthy value;
3976 * deletes all other elements; returns +self+:
3978 * a = [:foo, 'bar', 2, :bam]
3979 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3981 * Returns a new Enumerator if no block given:
3983 * a = [:foo, 'bar', 2, :bam]
3984 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3989 rb_ary_keep_if(VALUE ary
)
3991 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3992 rb_ary_select_bang(ary
);
3997 ary_resize_smaller(VALUE ary
, long len
)
4000 if (RARRAY_LEN(ary
) > len
) {
4001 ARY_SET_LEN(ary
, len
);
4002 if (len
* 2 < ARY_CAPA(ary
) &&
4003 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
4004 ary_resize_capa(ary
, len
* 2);
4011 * delete(object) -> last_removed_object
4012 * delete(object) {|element| ... } -> last_removed_object or block_return
4014 * Removes zero or more elements from +self+.
4016 * With no block given,
4017 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4018 * returns the last removed element:
4020 * a = [0, 1, 2, 2.0]
4021 * a.delete(2) # => 2.0
4024 * Returns +nil+ if no elements removed:
4026 * a.delete(2) # => nil
4028 * With a block given,
4029 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4031 * If any such elements are found, ignores the block
4032 * and returns the last removed element:
4034 * a = [0, 1, 2, 2.0]
4035 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4038 * If no such element is found, returns the block's return value:
4040 * a.delete(2) {|element| "Element #{element} not found." }
4041 * # => "Element 2 not found."
4043 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4047 rb_ary_delete(VALUE ary
, VALUE item
)
4052 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4053 VALUE e
= RARRAY_AREF(ary
, i1
);
4055 if (rb_equal(e
, item
)) {
4060 rb_ary_store(ary
, i2
, e
);
4064 if (RARRAY_LEN(ary
) == i2
) {
4065 if (rb_block_given_p()) {
4066 return rb_yield(item
);
4071 ary_resize_smaller(ary
, i2
);
4078 rb_ary_delete_same(VALUE ary
, VALUE item
)
4082 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4083 VALUE e
= RARRAY_AREF(ary
, i1
);
4089 rb_ary_store(ary
, i2
, e
);
4093 if (RARRAY_LEN(ary
) == i2
) {
4097 ary_resize_smaller(ary
, i2
);
4101 rb_ary_delete_at(VALUE ary
, long pos
)
4103 long len
= RARRAY_LEN(ary
);
4106 if (pos
>= len
) return Qnil
;
4109 if (pos
< 0) return Qnil
;
4113 del
= RARRAY_AREF(ary
, pos
);
4114 RARRAY_PTR_USE(ary
, ptr
, {
4115 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4117 ARY_INCREASE_LEN(ary
, -1);
4124 * delete_at(index) -> removed_object or nil
4126 * Removes the element of +self+ at the given +index+, which must be an
4127 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4129 * When +index+ is non-negative, deletes the element at offset +index+:
4131 * a = [:foo, 'bar', 2]
4132 * a.delete_at(1) # => "bar"
4135 * When +index+ is negative, counts backward from the end of the array:
4137 * a = [:foo, 'bar', 2]
4138 * a.delete_at(-2) # => "bar"
4141 * When +index+ is out of range, returns +nil+.
4143 * a = [:foo, 'bar', 2]
4144 * a.delete_at(3) # => nil
4145 * a.delete_at(-4) # => nil
4147 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4151 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4153 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4157 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4159 const long orig_len
= RARRAY_LEN(ary
);
4164 else if (pos
< -orig_len
) {
4170 else if (orig_len
< pos
) {
4173 if (orig_len
< pos
+ len
) {
4174 len
= orig_len
- pos
;
4177 return rb_ary_new2(0);
4180 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4181 rb_ary_splice(ary
, pos
, len
, 0, 0);
4188 * array.slice!(n) -> object or nil
4189 * array.slice!(start, length) -> new_array or nil
4190 * array.slice!(range) -> new_array or nil
4192 * Removes and returns elements from +self+.
4194 * When the only argument is an Integer +n+,
4195 * removes and returns the _nth_ element in +self+:
4197 * a = [:foo, 'bar', 2]
4198 * a.slice!(1) # => "bar"
4201 * If +n+ is negative, counts backwards from the end of +self+:
4203 * a = [:foo, 'bar', 2]
4204 * a.slice!(-1) # => 2
4205 * a # => [:foo, "bar"]
4207 * If +n+ is out of range, returns +nil+.
4209 * When the only arguments are Integers +start+ and +length+,
4210 * removes +length+ elements from +self+ beginning at offset +start+;
4211 * returns the deleted objects in a new +Array+:
4213 * a = [:foo, 'bar', 2]
4214 * a.slice!(0, 2) # => [:foo, "bar"]
4217 * If <tt>start + length</tt> exceeds the array size,
4218 * removes and returns all elements from offset +start+ to the end:
4220 * a = [:foo, 'bar', 2]
4221 * a.slice!(1, 50) # => ["bar", 2]
4224 * If <tt>start == a.size</tt> and +length+ is non-negative,
4225 * returns a new empty +Array+.
4227 * If +length+ is negative, returns +nil+.
4229 * When the only argument is a Range object +range+,
4230 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4232 * a = [:foo, 'bar', 2]
4233 * a.slice!(1..2) # => ["bar", 2]
4236 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4238 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4240 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4242 * a = [:foo, 'bar', 2]
4243 * a.slice!(0..-2) # => [:foo, "bar"]
4246 * If <tt>range.start</tt> is negative,
4247 * calculates the start index backwards from the end of the array:
4249 * a = [:foo, 'bar', 2]
4250 * a.slice!(-2..2) # => ["bar", 2]
4256 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4261 rb_ary_modify_check(ary
);
4262 rb_check_arity(argc
, 1, 2);
4266 pos
= NUM2LONG(argv
[0]);
4267 len
= NUM2LONG(argv
[1]);
4268 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4271 if (!FIXNUM_P(arg1
)) {
4272 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4275 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4285 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4289 ary_reject(VALUE orig
, VALUE result
)
4293 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4294 VALUE v
= RARRAY_AREF(orig
, i
);
4296 if (!RTEST(rb_yield(v
))) {
4297 rb_ary_push(result
, v
);
4304 reject_bang_i(VALUE a
)
4306 volatile struct select_bang_arg
*arg
= (void *)a
;
4307 VALUE ary
= arg
->ary
;
4310 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4311 VALUE v
= RARRAY_AREF(ary
, i1
);
4312 if (RTEST(rb_yield(v
))) continue;
4314 rb_ary_store(ary
, i2
, v
);
4318 return (i1
== i2
) ? Qnil
: ary
;
4322 ary_reject_bang(VALUE ary
)
4324 struct select_bang_arg args
;
4325 rb_ary_modify_check(ary
);
4327 args
.len
[0] = args
.len
[1] = 0;
4328 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4333 * array.reject! {|element| ... } -> self or nil
4334 * array.reject! -> new_enumerator
4336 * Removes each element for which the block returns a truthy value.
4338 * Returns +self+ if any elements removed:
4340 * a = [:foo, 'bar', 2, 'bat']
4341 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4343 * Returns +nil+ if no elements removed.
4345 * Returns a new Enumerator if no block given:
4347 * a = [:foo, 'bar', 2]
4348 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4353 rb_ary_reject_bang(VALUE ary
)
4355 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4357 return ary_reject_bang(ary
);
4362 * array.reject {|element| ... } -> new_array
4363 * array.reject -> new_enumerator
4365 * Returns a new +Array+ whose elements are all those from +self+
4366 * for which the block returns +false+ or +nil+:
4368 * a = [:foo, 'bar', 2, 'bat']
4369 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4372 * Returns a new Enumerator if no block given:
4374 * a = [:foo, 'bar', 2]
4375 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4380 rb_ary_reject(VALUE ary
)
4384 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4385 rejected_ary
= rb_ary_new();
4386 ary_reject(ary
, rejected_ary
);
4387 return rejected_ary
;
4392 * delete_if {|element| ... } -> self
4393 * delete_if -> new_numerator
4395 * With a block given, calls the block with each element of +self+;
4396 * removes the element if the block returns a truthy value;
4399 * a = [:foo, 'bar', 2, 'bat']
4400 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4402 * With no block given, returns a new Enumerator.
4404 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4408 rb_ary_delete_if(VALUE ary
)
4411 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4412 ary_reject_bang(ary
);
4417 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4419 VALUE
*args
= (VALUE
*)cbarg
;
4420 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4421 rb_ary_push(args
[0], val
);
4422 if (--args
[1] == 0) rb_iter_break();
4427 take_items(VALUE obj
, long n
)
4429 VALUE result
= rb_check_array_type(obj
);
4432 if (n
== 0) return result
;
4433 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4434 result
= rb_ary_new2(n
);
4435 args
[0] = result
; args
[1] = (VALUE
)n
;
4436 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4437 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4445 * array.zip(*other_arrays) -> new_array
4446 * array.zip(*other_arrays) {|other_array| ... } -> nil
4448 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4449 * whose elements are Arrays.
4451 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4454 * - The _nth_ element of +self+.
4455 * - The _nth_ element of each of the +other_arrays+.
4457 * If all +other_arrays+ and +self+ are the same size:
4459 * a = [:a0, :a1, :a2, :a3]
4460 * b = [:b0, :b1, :b2, :b3]
4461 * c = [:c0, :c1, :c2, :c3]
4463 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4465 * If any array in +other_arrays+ is smaller than +self+,
4466 * fills to <tt>self.size</tt> with +nil+:
4468 * a = [:a0, :a1, :a2, :a3]
4469 * b = [:b0, :b1, :b2]
4472 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4474 * If any array in +other_arrays+ is larger than +self+,
4475 * its trailing elements are ignored:
4477 * a = [:a0, :a1, :a2, :a3]
4478 * b = [:b0, :b1, :b2, :b3, :b4]
4479 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4481 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4483 * If an argument is not an array, it extracts the values by calling #each:
4485 * a = [:a0, :a1, :a2, :a2]
4488 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4490 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4492 * a = [:a0, :a1, :a2, :a3]
4493 * b = [:b0, :b1, :b2, :b3]
4494 * c = [:c0, :c1, :c2, :c3]
4495 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4507 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4510 long len
= RARRAY_LEN(ary
);
4511 VALUE result
= Qnil
;
4513 for (i
=0; i
<argc
; i
++) {
4514 argv
[i
] = take_items(argv
[i
], len
);
4517 if (rb_block_given_p()) {
4518 int arity
= rb_block_arity();
4523 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4525 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4526 tmp
[0] = RARRAY_AREF(ary
, i
);
4527 for (j
=0; j
<argc
; j
++) {
4528 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4530 rb_yield_values2(argc
+1, tmp
);
4533 if (work
) ALLOCV_END(work
);
4536 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4537 VALUE tmp
= rb_ary_new2(argc
+1);
4539 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4540 for (j
=0; j
<argc
; j
++) {
4541 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4548 result
= rb_ary_new_capa(len
);
4550 for (i
=0; i
<len
; i
++) {
4551 VALUE tmp
= rb_ary_new_capa(argc
+1);
4553 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4554 for (j
=0; j
<argc
; j
++) {
4555 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4557 rb_ary_push(result
, tmp
);
4566 * array.transpose -> new_array
4568 * Transposes the rows and columns in an +Array+ of Arrays;
4569 * the nested Arrays must all be the same size:
4571 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4572 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4577 rb_ary_transpose(VALUE ary
)
4579 long elen
= -1, alen
, i
, j
;
4580 VALUE tmp
, result
= 0;
4582 alen
= RARRAY_LEN(ary
);
4583 if (alen
== 0) return rb_ary_dup(ary
);
4584 for (i
=0; i
<alen
; i
++) {
4585 tmp
= to_ary(rb_ary_elt(ary
, i
));
4586 if (elen
< 0) { /* first element */
4587 elen
= RARRAY_LEN(tmp
);
4588 result
= rb_ary_new2(elen
);
4589 for (j
=0; j
<elen
; j
++) {
4590 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4593 else if (elen
!= RARRAY_LEN(tmp
)) {
4594 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4595 RARRAY_LEN(tmp
), elen
);
4597 for (j
=0; j
<elen
; j
++) {
4598 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4606 * array.replace(other_array) -> self
4608 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4610 * a = [:foo, 'bar', 2]
4611 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4616 rb_ary_replace(VALUE copy
, VALUE orig
)
4618 rb_ary_modify_check(copy
);
4619 orig
= to_ary(orig
);
4620 if (copy
== orig
) return copy
;
4624 /* orig has enough space to embed the contents of orig. */
4625 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4626 RUBY_ASSERT(ARY_EMBED_P(copy
));
4627 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4628 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4630 /* orig is embedded but copy does not have enough space to embed the
4631 * contents of orig. */
4632 else if (ARY_EMBED_P(orig
)) {
4633 long len
= ARY_EMBED_LEN(orig
);
4634 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4636 FL_UNSET_EMBED(copy
);
4637 ARY_SET_PTR(copy
, ptr
);
4638 ARY_SET_LEN(copy
, len
);
4639 ARY_SET_CAPA(copy
, len
);
4641 // No allocation and exception expected that could leave `copy` in a
4642 // bad state from the edits above.
4643 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4645 /* Otherwise, orig is on heap and copy does not have enough space to embed
4646 * the contents of orig. */
4648 VALUE shared_root
= ary_make_shared(orig
);
4649 FL_UNSET_EMBED(copy
);
4650 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4651 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4652 rb_ary_set_shared(copy
, shared_root
);
4662 * Removes all elements from +self+; returns +self+:
4664 * a = [:foo, 'bar', 2]
4667 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4671 rb_ary_clear(VALUE ary
)
4673 rb_ary_modify_check(ary
);
4674 if (ARY_SHARED_P(ary
)) {
4675 rb_ary_unshare(ary
);
4677 ARY_SET_EMBED_LEN(ary
, 0);
4680 ARY_SET_LEN(ary
, 0);
4681 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4682 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4691 * array.fill(obj) -> self
4692 * array.fill(obj, start) -> self
4693 * array.fill(obj, start, length) -> self
4694 * array.fill(obj, range) -> self
4695 * array.fill {|index| ... } -> self
4696 * array.fill(start) {|index| ... } -> self
4697 * array.fill(start, length) {|index| ... } -> self
4698 * array.fill(range) {|index| ... } -> self
4700 * Replaces specified elements in +self+ with specified objects; returns +self+.
4702 * With argument +obj+ and no block given, replaces all elements with that one object:
4704 * a = ['a', 'b', 'c', 'd']
4705 * a # => ["a", "b", "c", "d"]
4706 * a.fill(:X) # => [:X, :X, :X, :X]
4708 * With arguments +obj+ and Integer +start+, and no block given,
4709 * replaces elements based on the given start.
4711 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4712 * replaces all elements from offset +start+ through the end:
4714 * a = ['a', 'b', 'c', 'd']
4715 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4717 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4719 * a = ['a', 'b', 'c', 'd']
4720 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4721 * a = ['a', 'b', 'c', 'd']
4722 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4724 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4726 * a = ['a', 'b', 'c', 'd']
4727 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4729 * If +start+ is too small (less than and far from zero), replaces all elements:
4731 * a = ['a', 'b', 'c', 'd']
4732 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4733 * a = ['a', 'b', 'c', 'd']
4734 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4736 * With arguments +obj+, Integer +start+, and Integer +length+, and no block given,
4737 * replaces elements based on the given +start+ and +length+.
4739 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4741 * a = ['a', 'b', 'c', 'd']
4742 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4744 * If +start+ is negative, counts from the end:
4746 * a = ['a', 'b', 'c', 'd']
4747 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4749 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4751 * a = ['a', 'b', 'c', 'd']
4752 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4753 * a = ['a', 'b', 'c', 'd']
4754 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4756 * If +length+ is zero or negative, replaces no elements:
4758 * a = ['a', 'b', 'c', 'd']
4759 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4760 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4762 * With arguments +obj+ and Range +range+, and no block given,
4763 * replaces elements based on the given range.
4765 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4766 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4768 * a = ['a', 'b', 'c', 'd']
4769 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4771 * If <tt>range.first</tt> is negative, replaces no elements:
4773 * a = ['a', 'b', 'c', 'd']
4774 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4776 * If <tt>range.last</tt> is negative, counts from the end:
4778 * a = ['a', 'b', 'c', 'd']
4779 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4780 * a = ['a', 'b', 'c', 'd']
4781 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4783 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4784 * both count from the end of the array:
4786 * a = ['a', 'b', 'c', 'd']
4787 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4788 * a = ['a', 'b', 'c', 'd']
4789 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4791 * With no arguments and a block given, calls the block with each index;
4792 * replaces the corresponding element with the block's return value:
4794 * a = ['a', 'b', 'c', 'd']
4795 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4797 * With argument +start+ and a block given, calls the block with each index
4798 * from offset +start+ to the end; replaces the corresponding element
4799 * with the block's return value.
4801 * If start is in range (<tt>0 <= start < array.size</tt>),
4802 * replaces from offset +start+ to the end:
4804 * a = ['a', 'b', 'c', 'd']
4805 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4807 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4809 * a = ['a', 'b', 'c', 'd']
4810 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4811 * a = ['a', 'b', 'c', 'd']
4812 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4814 * If +start+ is negative, counts from the end:
4816 * a = ['a', 'b', 'c', 'd']
4817 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4819 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4821 * a = ['a', 'b', 'c', 'd']
4822 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4823 * a = ['a', 'b', 'c', 'd']
4824 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4826 * With arguments +start+ and +length+, and a block given,
4827 * calls the block for each index specified by start length;
4828 * replaces the corresponding element with the block's return value.
4830 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4832 * a = ['a', 'b', 'c', 'd']
4833 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4835 * If start is negative, counts from the end:
4837 * a = ['a', 'b', 'c', 'd']
4838 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4840 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4842 * a = ['a', 'b', 'c', 'd']
4843 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4844 * a = ['a', 'b', 'c', 'd']
4845 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4847 * If +length+ is zero or less, replaces no elements:
4849 * a = ['a', 'b', 'c', 'd']
4850 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4851 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4853 * With arguments +obj+ and +range+, and a block given,
4854 * calls the block with each index in the given range;
4855 * replaces the corresponding element with the block's return value.
4857 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4858 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4860 * a = ['a', 'b', 'c', 'd']
4861 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4863 * If +range.first+ is negative, does nothing:
4865 * a = ['a', 'b', 'c', 'd']
4866 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4868 * If <tt>range.last</tt> is negative, counts from the end:
4870 * a = ['a', 'b', 'c', 'd']
4871 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4872 * a = ['a', 'b', 'c', 'd']
4873 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4875 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4876 * both count from the end:
4878 * a = ['a', 'b', 'c', 'd']
4879 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4880 * a = ['a', 'b', 'c', 'd']
4881 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4886 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4888 VALUE item
= Qundef
, arg1
, arg2
;
4889 long beg
= 0, end
= 0, len
= 0;
4891 if (rb_block_given_p()) {
4892 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4893 argc
+= 1; /* hackish */
4896 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4901 len
= RARRAY_LEN(ary
);
4904 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4909 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4911 beg
= RARRAY_LEN(ary
) + beg
;
4912 if (beg
< 0) beg
= 0;
4914 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4921 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4922 rb_raise(rb_eArgError
, "argument too big");
4925 if (RARRAY_LEN(ary
) < end
) {
4926 if (end
>= ARY_CAPA(ary
)) {
4927 ary_resize_capa(ary
, end
);
4929 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4930 ARY_SET_LEN(ary
, end
);
4933 if (UNDEF_P(item
)) {
4937 for (i
=beg
; i
<end
; i
++) {
4938 v
= rb_yield(LONG2NUM(i
));
4939 if (i
>=RARRAY_LEN(ary
)) break;
4944 ary_memfill(ary
, beg
, len
, item
);
4951 * self + other_array -> new_array
4953 * Returns a new array containing all elements of +self+
4954 * followed by all elements of +other_array+:
4956 * a = [0, 1] + [2, 3]
4957 * a # => [0, 1, 2, 3]
4959 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4963 rb_ary_plus(VALUE x
, VALUE y
)
4966 long len
, xlen
, ylen
;
4969 xlen
= RARRAY_LEN(x
);
4970 ylen
= RARRAY_LEN(y
);
4972 z
= rb_ary_new2(len
);
4974 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
4975 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
4976 ARY_SET_LEN(z
, len
);
4981 ary_append(VALUE x
, VALUE y
)
4983 long n
= RARRAY_LEN(y
);
4985 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
4993 * concat(*other_arrays) -> self
4995 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4998 * a.concat(['two', 'three'], [:four, :five], a)
4999 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5001 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5005 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
5007 rb_ary_modify_check(ary
);
5010 rb_ary_concat(ary
, argv
[0]);
5012 else if (argc
> 1) {
5014 VALUE args
= rb_ary_hidden_new(argc
);
5015 for (i
= 0; i
< argc
; i
++) {
5016 rb_ary_concat(args
, argv
[i
]);
5018 ary_append(ary
, args
);
5026 rb_ary_concat(VALUE x
, VALUE y
)
5028 return ary_append(x
, to_ary(y
));
5033 * self * n -> new_array
5034 * self * string_separator -> new_string
5036 * When non-negative integer argument +n+ is given,
5037 * returns a new array built by concatenating +n+ copies of +self+:
5040 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5042 * When string argument +string_separator+ is given,
5043 * equivalent to <tt>array.join(string_separator)</tt>:
5045 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5050 rb_ary_times(VALUE ary
, VALUE times
)
5056 tmp
= rb_check_string_type(times
);
5058 return rb_ary_join(ary
, tmp
);
5061 len
= NUM2LONG(times
);
5063 ary2
= ary_new(rb_cArray
, 0);
5067 rb_raise(rb_eArgError
, "negative argument");
5069 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
5070 rb_raise(rb_eArgError
, "argument too big");
5072 len
*= RARRAY_LEN(ary
);
5074 ary2
= ary_new(rb_cArray
, len
);
5075 ARY_SET_LEN(ary2
, len
);
5077 ptr
= RARRAY_CONST_PTR(ary
);
5078 t
= RARRAY_LEN(ary
);
5080 ary_memcpy(ary2
, 0, t
, ptr
);
5081 while (t
<= len
/2) {
5082 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5086 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5095 * assoc(object) -> found_array or nil
5097 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5098 * and <tt>ele[0] == object</tt>:
5100 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5101 * a.assoc(4) # => [4, 5, 6]
5103 * Returns +nil+ if no such element is found.
5105 * Related: Array#rassoc;
5106 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5110 rb_ary_assoc(VALUE ary
, VALUE key
)
5115 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5116 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5117 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5118 rb_equal(RARRAY_AREF(v
, 0), key
))
5126 * array.rassoc(obj) -> found_array or nil
5128 * Returns the first element in +self+ that is an +Array+
5129 * whose second element <tt>==</tt> +obj+:
5131 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5132 * a.rassoc(4) # => [2, 4]
5134 * Returns +nil+ if no such element is found.
5140 rb_ary_rassoc(VALUE ary
, VALUE value
)
5145 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5146 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5147 if (RB_TYPE_P(v
, T_ARRAY
) &&
5148 RARRAY_LEN(v
) > 1 &&
5149 rb_equal(RARRAY_AREF(v
, 1), value
))
5156 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5159 const VALUE
*p1
, *p2
;
5161 if (recur
) return Qtrue
; /* Subtle! */
5163 /* rb_equal() can evacuate ptrs */
5164 p1
= RARRAY_CONST_PTR(ary1
);
5165 p2
= RARRAY_CONST_PTR(ary2
);
5166 len1
= RARRAY_LEN(ary1
);
5168 for (i
= 0; i
< len1
; i
++) {
5170 if (rb_equal(*p1
, *p2
)) {
5171 len1
= RARRAY_LEN(ary1
);
5172 if (len1
!= RARRAY_LEN(ary2
))
5176 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5177 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5191 * self == other_array -> true or false
5193 * Returns whether both:
5195 * - +self+ and +other_array+ are the same size.
5196 * - Their corresponding elements are the same;
5197 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5198 * <tt>self[i] == other_array[i]</tt>.
5202 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5203 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5204 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5205 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5207 * This method is different from method Array#eql?,
5208 * which compares elements using <tt>Object#eql?</tt>.
5210 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5214 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5216 if (ary1
== ary2
) return Qtrue
;
5217 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5218 if (!rb_respond_to(ary2
, idTo_ary
)) {
5221 return rb_equal(ary2
, ary1
);
5223 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5224 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5225 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5229 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5233 if (recur
) return Qtrue
; /* Subtle! */
5234 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5235 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5243 * eql?(other_array) -> true or false
5245 * Returns +true+ if +self+ and +other_array+ are the same size,
5246 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5248 * a0 = [:foo, 'bar', 2]
5249 * a1 = [:foo, 'bar', 2]
5250 * a1.eql?(a0) # => true
5252 * Otherwise, returns +false+.
5254 * This method is different from method Array#==,
5255 * which compares using method <tt>Object#==</tt>.
5257 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5261 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5263 if (ary1
== ary2
) return Qtrue
;
5264 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5265 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5266 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5267 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5271 rb_ary_hash_values(long len
, const VALUE
*elements
)
5277 h
= rb_hash_start(len
);
5278 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5279 for (i
=0; i
<len
; i
++) {
5280 n
= rb_hash(elements
[i
]);
5281 h
= rb_hash_uint(h
, NUM2LONG(n
));
5289 * array.hash -> integer
5291 * Returns the integer hash value for +self+.
5293 * Two arrays with the same content will have the same hash code (and will compare using #eql?):
5295 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5296 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5301 rb_ary_hash(VALUE ary
)
5303 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5308 * array.include?(obj) -> true or false
5310 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5311 * otherwise +false+:
5313 * [0, 1, 2].include?(2) # => true
5314 * [0, 1, 2].include?(3) # => false
5318 rb_ary_includes(VALUE ary
, VALUE item
)
5323 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5324 e
= RARRAY_AREF(ary
, i
);
5325 if (rb_equal(e
, item
)) {
5333 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5338 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5339 e
= RARRAY_AREF(ary
, i
);
5340 if (rb_eql(item
, e
)) {
5348 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5352 if (recur
) return Qundef
; /* Subtle! */
5353 len
= RARRAY_LEN(ary1
);
5354 if (len
> RARRAY_LEN(ary2
)) {
5355 len
= RARRAY_LEN(ary2
);
5357 for (i
=0; i
<len
; i
++) {
5358 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5359 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5360 if (v
!= INT2FIX(0)) {
5369 * self <=> other_array -> -1, 0, or 1
5371 * Returns -1, 0, or 1 as +self+ is determined
5372 * to be less than, equal to, or greater than +other_array+.
5374 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5376 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5377 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5379 * [0, 1, 2] <=> [0, 0, 2] # => 1
5381 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5383 * [0, 1, 2] <=> [0, 2, 2] # => -1
5385 * - Continues if <tt>result[i]</tt> is 0.
5387 * When every +result+ is 0,
5388 * returns <tt>self.size <=> other_array.size</tt>
5389 * (see Integer#<=>):
5391 * [0, 1, 2] <=> [0, 1] # => 1
5392 * [0, 1, 2] <=> [0, 1, 2] # => 0
5393 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5395 * Note that when +other_array+ is larger than +self+,
5396 * its trailing elements do not affect the result:
5398 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5399 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5400 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5402 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5406 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5411 ary2
= rb_check_array_type(ary2
);
5412 if (NIL_P(ary2
)) return Qnil
;
5413 if (ary1
== ary2
) return INT2FIX(0);
5414 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5415 if (!UNDEF_P(v
)) return v
;
5416 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5417 if (len
== 0) return INT2FIX(0);
5418 if (len
> 0) return INT2FIX(1);
5423 ary_add_hash(VALUE hash
, VALUE ary
)
5427 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5428 VALUE elt
= RARRAY_AREF(ary
, i
);
5429 rb_hash_add_new_element(hash
, elt
, elt
);
5435 ary_tmp_hash_new(VALUE ary
)
5437 long size
= RARRAY_LEN(ary
);
5438 VALUE hash
= rb_hash_new_with_size(size
);
5440 RBASIC_CLEAR_CLASS(hash
);
5445 ary_make_hash(VALUE ary
)
5447 VALUE hash
= ary_tmp_hash_new(ary
);
5448 return ary_add_hash(hash
, ary
);
5452 ary_add_hash_by(VALUE hash
, VALUE ary
)
5456 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5457 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5458 rb_hash_add_new_element(hash
, k
, v
);
5464 ary_make_hash_by(VALUE ary
)
5466 VALUE hash
= ary_tmp_hash_new(ary
);
5467 return ary_add_hash_by(hash
, ary
);
5472 * self - other_array -> new_array
5474 * Returns a new array containing only those elements of +self+
5475 * that are not found in +other_array+;
5476 * the order from +self+ is preserved:
5478 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5479 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5480 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5482 * Element are compared using method <tt>#eql?</tt>
5483 * (as defined in each element of +self+).
5485 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5489 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5495 ary2
= to_ary(ary2
);
5496 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5497 ary3
= rb_ary_new();
5499 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5500 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5501 VALUE elt
= rb_ary_elt(ary1
, i
);
5502 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5503 rb_ary_push(ary3
, elt
);
5508 hash
= ary_make_hash(ary2
);
5509 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5510 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5511 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5519 * difference(*other_arrays = []) -> new_array
5521 * Returns a new array containing only those elements from +self+
5522 * that are not found in any of the given +other_arrays+;
5523 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5525 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5526 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5527 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5528 * [0, 1, 2].difference # => [0, 1, 2]
5530 * Returns a copy of +self+ if no arguments are given.
5533 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5537 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5542 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5543 ary_diff
= rb_ary_new();
5544 length
= RARRAY_LEN(ary
);
5546 for (i
= 0; i
< argc
; i
++) {
5547 argv
[i
] = to_ary(argv
[i
]);
5548 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5549 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5552 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5554 VALUE elt
= rb_ary_elt(ary
, i
);
5555 for (j
= 0; j
< argc
; j
++) {
5557 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5561 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5564 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5575 * self & other_array -> new_array
5577 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5578 * that is, containing those elements found in both +self+ and +other_array+:
5580 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5584 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5586 * Preserves order from +self+:
5588 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5590 * Identifies common elements using method <tt>#eql?</tt>
5591 * (as defined in each element of +self+).
5593 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5598 rb_ary_and(VALUE ary1
, VALUE ary2
)
5600 VALUE hash
, ary3
, v
;
5604 ary2
= to_ary(ary2
);
5605 ary3
= rb_ary_new();
5606 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5608 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5609 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5610 v
= RARRAY_AREF(ary1
, i
);
5611 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5612 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5613 rb_ary_push(ary3
, v
);
5618 hash
= ary_make_hash(ary2
);
5620 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5621 v
= RARRAY_AREF(ary1
, i
);
5623 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5624 rb_ary_push(ary3
, v
);
5633 * array.intersection(*other_arrays) -> new_array
5635 * Returns a new +Array+ containing each element found both in +self+
5636 * and in all of the given Arrays +other_arrays+;
5637 * duplicates are omitted; items are compared using <tt>eql?</tt>
5638 * (items must also implement +hash+ correctly):
5640 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5641 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5643 * Preserves order from +self+:
5645 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5647 * Returns a copy of +self+ if no arguments given.
5653 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5655 VALUE result
= rb_ary_dup(ary
);
5658 for (i
= 0; i
< argc
; i
++) {
5659 result
= rb_ary_and(result
, argv
[i
]);
5666 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5668 if (existing
) return ST_STOP
;
5669 *key
= *value
= (VALUE
)arg
;
5674 rb_ary_union(VALUE ary_union
, VALUE ary
)
5677 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5678 VALUE elt
= rb_ary_elt(ary
, i
);
5679 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5680 rb_ary_push(ary_union
, elt
);
5685 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5688 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5689 VALUE elt
= RARRAY_AREF(ary2
, i
);
5690 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5691 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5698 * array | other_array -> new_array
5700 * Returns the union of +array+ and +Array+ +other_array+;
5701 * duplicates are removed; order is preserved;
5702 * items are compared using <tt>eql?</tt>:
5704 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5705 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5706 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5708 * Related: Array#union.
5712 rb_ary_or(VALUE ary1
, VALUE ary2
)
5716 ary2
= to_ary(ary2
);
5717 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5718 VALUE ary3
= rb_ary_new();
5719 rb_ary_union(ary3
, ary1
);
5720 rb_ary_union(ary3
, ary2
);
5724 hash
= ary_make_hash(ary1
);
5725 rb_ary_union_hash(hash
, ary2
);
5727 return rb_hash_values(hash
);
5732 * array.union(*other_arrays) -> new_array
5734 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5735 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5737 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5738 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5739 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5741 * Returns a copy of +self+ if no arguments given.
5747 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5753 sum
= RARRAY_LEN(ary
);
5754 for (i
= 0; i
< argc
; i
++) {
5755 argv
[i
] = to_ary(argv
[i
]);
5756 sum
+= RARRAY_LEN(argv
[i
]);
5759 if (sum
<= SMALL_ARRAY_LEN
) {
5760 VALUE ary_union
= rb_ary_new();
5762 rb_ary_union(ary_union
, ary
);
5763 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5768 hash
= ary_make_hash(ary
);
5769 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5771 return rb_hash_values(hash
);
5776 * ary.intersect?(other_ary) -> true or false
5778 * Returns +true+ if the array and +other_ary+ have at least one element in
5779 * common, otherwise returns +false+:
5784 * a.intersect?(b) #=> true
5785 * a.intersect?(c) #=> false
5787 * +Array+ elements are compared using <tt>eql?</tt>
5788 * (items must also implement +hash+ correctly).
5792 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5794 VALUE hash
, v
, result
, shorter
, longer
;
5798 ary2
= to_ary(ary2
);
5799 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5801 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5802 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5803 v
= RARRAY_AREF(ary1
, i
);
5804 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5811 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5816 hash
= ary_make_hash(shorter
);
5819 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5820 v
= RARRAY_AREF(longer
, i
);
5822 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5832 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5834 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5837 for (; i
< RARRAY_LEN(ary
); ++i
) {
5838 v
= RARRAY_AREF(ary
, i
);
5840 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5849 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5851 const long n
= RARRAY_LEN(ary
);
5852 RUBY_ASSERT(i
> 0 && i
< n
);
5853 RUBY_ASSERT(FIXNUM_P(vmax
));
5856 for (; i
< n
; ++i
) {
5857 v
= RARRAY_AREF(ary
, i
);
5860 if ((long)vmax
< (long)v
) {
5865 return ary_max_generic(ary
, i
, vmax
);
5873 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5875 const long n
= RARRAY_LEN(ary
);
5876 RUBY_ASSERT(i
> 0 && i
< n
);
5877 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5880 for (; i
< n
; ++i
) {
5881 v
= RARRAY_AREF(ary
, i
);
5883 if (RB_FLOAT_TYPE_P(v
)) {
5884 if (rb_float_cmp(vmax
, v
) < 0) {
5889 return ary_max_generic(ary
, i
, vmax
);
5897 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5899 const long n
= RARRAY_LEN(ary
);
5900 RUBY_ASSERT(i
> 0 && i
< n
);
5901 RUBY_ASSERT(STRING_P(vmax
));
5904 for (; i
< n
; ++i
) {
5905 v
= RARRAY_AREF(ary
, i
);
5908 if (rb_str_cmp(vmax
, v
) < 0) {
5913 return ary_max_generic(ary
, i
, vmax
);
5922 * array.max -> element
5923 * array.max {|a, b| ... } -> element
5924 * array.max(n) -> new_array
5925 * array.max(n) {|a, b| ... } -> new_array
5927 * Returns one of the following:
5929 * - The maximum-valued element from +self+.
5930 * - A new +Array+ of maximum-valued elements selected from +self+.
5932 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5935 * With no argument and no block, returns the element in +self+
5936 * having the maximum value per method <tt><=></tt>:
5938 * [0, 1, 2].max # => 2
5940 * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
5941 * in descending order per method <tt><=></tt>:
5943 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5944 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5946 * When a block is given, the block must return an Integer.
5948 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5949 * returns the element having the maximum value per the block:
5951 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5953 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
5954 * in descending order per the block:
5956 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5960 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
5962 VALUE result
= Qundef
, v
;
5966 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5967 return rb_nmin_run(ary
, num
, 0, 1, 1);
5969 const long n
= RARRAY_LEN(ary
);
5970 if (rb_block_given_p()) {
5971 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5972 v
= RARRAY_AREF(ary
, i
);
5973 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
5979 result
= RARRAY_AREF(ary
, 0);
5981 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
5982 return ary_max_opt_fixnum(ary
, 1, result
);
5984 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
5985 return ary_max_opt_string(ary
, 1, result
);
5987 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
5988 return ary_max_opt_float(ary
, 1, result
);
5991 return ary_max_generic(ary
, 1, result
);
5995 if (UNDEF_P(result
)) return Qnil
;
6000 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
6002 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
6005 for (; i
< RARRAY_LEN(ary
); ++i
) {
6006 v
= RARRAY_AREF(ary
, i
);
6008 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
6017 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
6019 const long n
= RARRAY_LEN(ary
);
6020 RUBY_ASSERT(i
> 0 && i
< n
);
6021 RUBY_ASSERT(FIXNUM_P(vmin
));
6024 for (; i
< n
; ++i
) {
6025 a
= RARRAY_AREF(ary
, i
);
6028 if ((long)vmin
> (long)a
) {
6033 return ary_min_generic(ary
, i
, vmin
);
6041 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
6043 const long n
= RARRAY_LEN(ary
);
6044 RUBY_ASSERT(i
> 0 && i
< n
);
6045 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
6048 for (; i
< n
; ++i
) {
6049 a
= RARRAY_AREF(ary
, i
);
6051 if (RB_FLOAT_TYPE_P(a
)) {
6052 if (rb_float_cmp(vmin
, a
) > 0) {
6057 return ary_min_generic(ary
, i
, vmin
);
6065 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
6067 const long n
= RARRAY_LEN(ary
);
6068 RUBY_ASSERT(i
> 0 && i
< n
);
6069 RUBY_ASSERT(STRING_P(vmin
));
6072 for (; i
< n
; ++i
) {
6073 a
= RARRAY_AREF(ary
, i
);
6076 if (rb_str_cmp(vmin
, a
) > 0) {
6081 return ary_min_generic(ary
, i
, vmin
);
6090 * array.min -> element
6091 * array.min { |a, b| ... } -> element
6092 * array.min(n) -> new_array
6093 * array.min(n) { |a, b| ... } -> new_array
6095 * Returns one of the following:
6097 * - The minimum-valued element from +self+.
6098 * - A new +Array+ of minimum-valued elements selected from +self+.
6100 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6103 * With no argument and no block, returns the element in +self+
6104 * having the minimum value per method <tt><=></tt>:
6106 * [0, 1, 2].min # => 0
6108 * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
6109 * in ascending order per method <tt><=></tt>:
6111 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
6112 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
6114 * When a block is given, the block must return an Integer.
6116 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
6117 * returns the element having the minimum value per the block:
6119 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
6121 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
6122 * in ascending order per the block:
6124 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
6128 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6130 VALUE result
= Qundef
, v
;
6134 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6135 return rb_nmin_run(ary
, num
, 0, 0, 1);
6137 const long n
= RARRAY_LEN(ary
);
6138 if (rb_block_given_p()) {
6139 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6140 v
= RARRAY_AREF(ary
, i
);
6141 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6147 result
= RARRAY_AREF(ary
, 0);
6149 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6150 return ary_min_opt_fixnum(ary
, 1, result
);
6152 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6153 return ary_min_opt_string(ary
, 1, result
);
6155 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6156 return ary_min_opt_float(ary
, 1, result
);
6159 return ary_min_generic(ary
, 1, result
);
6163 if (UNDEF_P(result
)) return Qnil
;
6169 * array.minmax -> [min_val, max_val]
6170 * array.minmax {|a, b| ... } -> [min_val, max_val]
6172 * Returns a new 2-element +Array+ containing the minimum and maximum values
6173 * from +self+, either per method <tt><=></tt> or per a given block:.
6175 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6177 * returns a new 2-element +Array+ containing the minimum and maximum values
6178 * from +self+, per method <tt><=></tt>:
6180 * [0, 1, 2].minmax # => [0, 2]
6182 * When a block is given, the block must return an Integer;
6183 * the block is called <tt>self.size-1</tt> times to compare elements;
6184 * returns a new 2-element +Array+ containing the minimum and maximum values
6185 * from +self+, per the block:
6187 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
6191 rb_ary_minmax(VALUE ary
)
6193 if (rb_block_given_p()) {
6194 return rb_call_super(0, NULL
);
6196 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6200 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6202 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6208 * array.uniq! -> self or nil
6209 * array.uniq! {|element| ... } -> self or nil
6211 * Removes duplicate elements from +self+, the first occurrence always being retained;
6212 * returns +self+ if any elements removed, +nil+ otherwise.
6214 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6217 * Returns +self+ if any elements removed:
6219 * a = [0, 0, 1, 1, 2, 2]
6220 * a.uniq! # => [0, 1, 2]
6222 * Returns +nil+ if no elements removed.
6224 * With a block given, calls the block for each element;
6225 * identifies (using method <tt>eql?</tt>) and removes
6226 * elements for which the block returns duplicate values.
6228 * Returns +self+ if any elements removed:
6230 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6231 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6233 * Returns +nil+ if no elements removed.
6236 rb_ary_uniq_bang(VALUE ary
)
6241 rb_ary_modify_check(ary
);
6242 if (RARRAY_LEN(ary
) <= 1)
6244 if (rb_block_given_p())
6245 hash
= ary_make_hash_by(ary
);
6247 hash
= ary_make_hash(ary
);
6249 hash_size
= RHASH_SIZE(hash
);
6250 if (RARRAY_LEN(ary
) == hash_size
) {
6253 rb_ary_modify_check(ary
);
6254 ARY_SET_LEN(ary
, 0);
6255 if (ARY_SHARED_P(ary
)) {
6256 rb_ary_unshare(ary
);
6259 ary_resize_capa(ary
, hash_size
);
6260 rb_hash_foreach(hash
, push_value
, ary
);
6267 * array.uniq -> new_array
6268 * array.uniq {|element| ... } -> new_array
6270 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6271 * the first occurrence always being retained.
6273 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6276 * a = [0, 0, 1, 1, 2, 2]
6277 * a.uniq # => [0, 1, 2]
6279 * With a block given, calls the block for each element;
6280 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6281 * that is, those elements for which the block returns the same value:
6283 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6284 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6289 rb_ary_uniq(VALUE ary
)
6293 if (RARRAY_LEN(ary
) <= 1) {
6295 uniq
= rb_ary_dup(ary
);
6297 else if (rb_block_given_p()) {
6298 hash
= ary_make_hash_by(ary
);
6299 uniq
= rb_hash_values(hash
);
6302 hash
= ary_make_hash(ary
);
6303 uniq
= rb_hash_values(hash
);
6311 * compact! -> self or nil
6313 * Removes all +nil+ elements from +self+;
6314 * Returns +self+ if any elements are removed, +nil+ otherwise:
6316 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6317 * a.compact! # => [0, false, "", [], {}]
6318 * a # => [0, false, "", [], {}]
6319 * a.compact! # => nil
6321 * Related: Array#compact;
6322 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6326 rb_ary_compact_bang(VALUE ary
)
6332 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6333 end
= p
+ RARRAY_LEN(ary
);
6339 n
= p
- RARRAY_CONST_PTR(ary
);
6340 if (RARRAY_LEN(ary
) == n
) {
6343 ary_resize_smaller(ary
, n
);
6350 * compact -> new_array
6352 * Returns a new array containing only the non-+nil+ elements from +self+;
6353 * element order is preserved:
6355 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6356 * a.compact # => [0, false, "", [], {}]
6358 * Related: Array#compact!;
6359 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6363 rb_ary_compact(VALUE ary
)
6365 ary
= rb_ary_dup(ary
);
6366 rb_ary_compact_bang(ary
);
6373 * count(object) -> integer
6374 * count {|element| ... } -> integer
6376 * Returns a count of specified elements.
6378 * With no argument and no block, returns the count of all elements:
6380 * [0, :one, 'two', 3, 3.0].count # => 5
6382 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6384 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6386 * With no argument and a block given, calls the block with each element;
6387 * returns the count of elements for which the block returns a truthy value:
6389 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6391 * With argument +object+ and a block given, issues a warning, ignores the block,
6392 * and returns the count of elements <tt>==</tt> to +object+.
6394 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6398 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6402 if (rb_check_arity(argc
, 0, 1) == 0) {
6405 if (!rb_block_given_p())
6406 return LONG2NUM(RARRAY_LEN(ary
));
6408 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6409 v
= RARRAY_AREF(ary
, i
);
6410 if (RTEST(rb_yield(v
))) n
++;
6414 VALUE obj
= argv
[0];
6416 if (rb_block_given_p()) {
6417 rb_warn("given block not used");
6419 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6420 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6428 flatten(VALUE ary
, int level
)
6431 VALUE stack
, result
, tmp
= 0, elt
;
6432 VALUE memo
= Qfalse
;
6434 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6435 elt
= RARRAY_AREF(ary
, i
);
6436 tmp
= rb_check_array_type(elt
);
6441 if (i
== RARRAY_LEN(ary
)) {
6445 result
= ary_new(0, RARRAY_LEN(ary
));
6446 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6447 ARY_SET_LEN(result
, i
);
6449 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6450 rb_ary_push(stack
, ary
);
6451 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6454 memo
= rb_obj_hide(rb_ident_hash_new());
6455 rb_hash_aset(memo
, ary
, Qtrue
);
6456 rb_hash_aset(memo
, tmp
, Qtrue
);
6463 while (i
< RARRAY_LEN(ary
)) {
6464 elt
= RARRAY_AREF(ary
, i
++);
6465 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6466 rb_ary_push(result
, elt
);
6469 tmp
= rb_check_array_type(elt
);
6470 if (RBASIC(result
)->klass
) {
6472 rb_hash_clear(memo
);
6474 rb_raise(rb_eRuntimeError
, "flatten reentered");
6477 rb_ary_push(result
, elt
);
6481 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6482 rb_hash_clear(memo
);
6483 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6485 rb_hash_aset(memo
, tmp
, Qtrue
);
6487 rb_ary_push(stack
, ary
);
6488 rb_ary_push(stack
, LONG2NUM(i
));
6493 if (RARRAY_LEN(stack
) == 0) {
6497 rb_hash_delete(memo
, ary
);
6499 tmp
= rb_ary_pop(stack
);
6501 ary
= rb_ary_pop(stack
);
6505 rb_hash_clear(memo
);
6508 RBASIC_SET_CLASS(result
, rb_cArray
);
6514 * array.flatten! -> self or nil
6515 * array.flatten!(level) -> self or nil
6517 * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
6518 * returns +self+ if any changes, +nil+ otherwise.
6520 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6522 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6523 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6524 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6525 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6526 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6527 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6528 * [0, 1, 2].flatten!(1) # => nil
6530 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6532 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6533 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6534 * [0, 1, 2].flatten! # => nil
6535 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6536 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6537 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6538 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6539 * [0, 1, 2].flatten!(-1) # => nil
6544 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6546 int mod
= 0, level
= -1;
6549 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6550 rb_ary_modify_check(ary
);
6551 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6552 if (level
== 0) return Qnil
;
6554 result
= flatten(ary
, level
);
6555 if (result
== ary
) {
6558 if (!(mod
= ARY_EMBED_P(result
))) rb_ary_freeze(result
);
6559 rb_ary_replace(ary
, result
);
6560 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6567 * array.flatten -> new_array
6568 * array.flatten(level) -> new_array
6570 * Returns a new +Array+ that is a recursive flattening of +self+:
6571 * - Each non-Array element is unchanged.
6572 * - Each +Array+ is replaced by its individual elements.
6574 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6576 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6577 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6578 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6579 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6580 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6581 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6582 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6583 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6585 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6587 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6588 * a.flatten # => [0, 1, 2, 3, 4, 5]
6589 * [0, 1, 2].flatten # => [0, 1, 2]
6590 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6591 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6592 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6593 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6594 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6599 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6604 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6605 level
= NUM2INT(argv
[0]);
6606 if (level
== 0) return ary_make_shared_copy(ary
);
6609 result
= flatten(ary
, level
);
6610 if (result
== ary
) {
6611 result
= ary_make_shared_copy(ary
);
6617 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6620 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6625 i
= len
= RARRAY_LEN(ary
);
6626 RARRAY_PTR_USE(ary
, ptr
, {
6628 long j
= RAND_UPTO(i
);
6630 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6631 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6637 }); /* WB: no new reference */
6642 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6644 ary
= rb_ary_dup(ary
);
6645 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6649 static const rb_data_type_t ary_sample_memo_type
= {
6650 .wrap_struct_name
= "ary_sample_memo",
6652 .dfree
= (RUBY_DATA_FUNC
)st_free_table
,
6654 .flags
= RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_FREE_IMMEDIATELY
6658 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6661 long n
, len
, i
, j
, k
, idx
[10];
6662 long rnds
[numberof(idx
)];
6663 long memo_threshold
;
6665 len
= RARRAY_LEN(ary
);
6672 return rb_ary_elt(ary
, i
);
6675 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6676 if (n
> len
) n
= len
;
6677 if (n
<= numberof(idx
)) {
6678 for (i
= 0; i
< n
; ++i
) {
6679 rnds
[i
] = RAND_UPTO(len
- i
);
6683 len
= RARRAY_LEN(ary
);
6684 if (len
< k
&& n
<= numberof(idx
)) {
6685 for (i
= 0; i
< n
; ++i
) {
6686 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6689 if (n
> len
) n
= len
;
6692 return rb_ary_new_capa(0);
6695 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6700 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6707 if (j
>= i
) l
= i
, g
= ++j
;
6708 if (k
>= l
&& (++k
>= g
)) ++k
;
6710 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6713 len
< 2560 ? len
/ 128 :
6714 len
< 5120 ? len
/ 64 :
6715 len
< 10240 ? len
/ 32 :
6717 if (n
<= numberof(idx
)) {
6718 long sorted
[numberof(idx
)];
6719 sorted
[0] = idx
[0] = rnds
[0];
6720 for (i
=1; i
<n
; i
++) {
6722 for (j
= 0; j
< i
; ++j
) {
6723 if (k
< sorted
[j
]) break;
6726 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6727 sorted
[j
] = idx
[i
] = k
;
6729 result
= rb_ary_new_capa(n
);
6730 RARRAY_PTR_USE(result
, ptr_result
, {
6731 for (i
=0; i
<n
; i
++) {
6732 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6736 else if (n
<= memo_threshold
/ 2) {
6738 VALUE vmemo
= TypedData_Wrap_Struct(0, &ary_sample_memo_type
, 0);
6739 st_table
*memo
= st_init_numtable_with_size(n
);
6740 RTYPEDDATA_DATA(vmemo
) = memo
;
6741 result
= rb_ary_new_capa(n
);
6742 RARRAY_PTR_USE(result
, ptr_result
, {
6743 for (i
=0; i
<n
; i
++) {
6744 long r
= RAND_UPTO(len
-i
) + i
;
6746 if (r
> max_idx
) max_idx
= r
;
6748 len
= RARRAY_LEN(ary
);
6749 if (len
<= max_idx
) n
= 0;
6750 else if (n
> len
) n
= len
;
6751 RARRAY_PTR_USE(ary
, ptr_ary
, {
6752 for (i
=0; i
<n
; i
++) {
6753 long j2
= j
= ptr_result
[i
];
6756 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6757 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6758 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6759 ptr_result
[i
] = ptr_ary
[j2
];
6763 RTYPEDDATA_DATA(vmemo
) = 0;
6764 st_free_table(memo
);
6768 result
= rb_ary_dup(ary
);
6769 RBASIC_CLEAR_CLASS(result
);
6771 RARRAY_PTR_USE(result
, ptr_result
, {
6772 for (i
=0; i
<n
; i
++) {
6773 j
= RAND_UPTO(len
-i
) + i
;
6775 ptr_result
[j
] = ptr_result
[i
];
6779 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6781 ARY_SET_LEN(result
, n
);
6787 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6789 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6793 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6797 if (args
&& (RARRAY_LEN(args
) > 0)) {
6798 n
= RARRAY_AREF(args
, 0);
6800 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6801 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6803 if (mul
<= 0) return INT2FIX(0);
6805 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6810 * cycle(count = nil) {|element| ... } -> nil
6811 * cycle(count = nil) -> new_enumerator
6813 * With a block given, may call the block, depending on the value of argument +count+;
6814 * +count+ must be an
6815 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6818 * When +count+ is positive,
6819 * calls the block with each element, then does so repeatedly,
6820 * until it has done so +count+ times; returns +nil+:
6823 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6824 * output # => [0, 1, 0, 1]
6826 * When +count+ is zero or negative, does not call the block:
6828 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6829 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6831 * When +count+ is +nil+, cycles forever:
6833 * # Prints 0 and 1 forever.
6834 * [0, 1].cycle {|element| puts element }
6835 * [0, 1].cycle(nil) {|element| puts element }
6837 * With no block given, returns a new Enumerator.
6839 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6842 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6846 rb_check_arity(argc
, 0, 1);
6848 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6849 if (argc
== 0 || NIL_P(argv
[0])) {
6853 n
= NUM2LONG(argv
[0]);
6854 if (n
<= 0) return Qnil
;
6857 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6858 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6859 rb_yield(RARRAY_AREF(ary
, i
));
6866 * Build a ruby array of the corresponding values and yield it to the
6868 * Return the class of +values+ for reentry check.
6871 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6873 const VALUE result
= rb_ary_new2(r
);
6876 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6877 ARY_SET_LEN(result
, r
);
6879 return !RBASIC(values
)->klass
;
6883 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6885 * When we have a complete permutation of array indices, copy the values
6886 * at those indices into a new array and yield that array.
6888 * n: the size of the set
6889 * r: the number of elements in each permutation
6890 * p: the array (of size r) that we're filling in
6891 * used: an array of booleans: whether a given index is already used
6892 * values: the Ruby array that holds the actual values to permute
6895 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6897 long i
= 0, index
= 0;
6900 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6903 i
= p
[--index
]; /* pop index */
6904 used
[i
++] = 0; /* index unused */
6909 used
[i
] = 1; /* mark index used */
6911 if (index
< r
-1) { /* if not done yet */
6915 for (i
= 0; i
< n
; ++i
) {
6916 if (used
[i
]) continue;
6918 if (!yield_indexed_values(values
, r
, p
)) {
6919 rb_raise(rb_eRuntimeError
, "permute reentered");
6922 i
= p
[--index
]; /* pop index */
6923 used
[i
] = 0; /* index unused */
6930 * Returns the product of from, from-1, ..., from - how_many + 1.
6931 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6934 descending_factorial(long from
, long how_many
)
6938 cnt
= LONG2FIX(from
);
6939 while (--how_many
> 0) {
6941 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
6945 cnt
= LONG2FIX(how_many
== 0);
6951 binomial_coefficient(long comb
, long size
)
6955 if (comb
> size
-comb
) {
6961 else if (comb
== 0) {
6965 for (i
= 1; i
< comb
; ++i
) {
6966 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
6967 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
6973 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6975 long n
= RARRAY_LEN(ary
);
6976 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
6978 return descending_factorial(n
, k
);
6983 * array.permutation {|element| ... } -> self
6984 * array.permutation(n) {|element| ... } -> self
6985 * array.permutation -> new_enumerator
6986 * array.permutation(n) -> new_enumerator
6988 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6989 * The order of permutations is indeterminate.
6991 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6992 * are given, calls the block with all +n+-tuple permutations of +self+.
6997 * a.permutation(2) {|permutation| p permutation }
7011 * a.permutation(3) {|permutation| p permutation }
7022 * When +n+ is zero, calls the block once with a new empty +Array+:
7025 * a.permutation(0) {|permutation| p permutation }
7031 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7032 * does not call the block:
7035 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7036 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7038 * When a block given but no argument,
7039 * behaves the same as <tt>a.permutation(a.size)</tt>:
7042 * a.permutation {|permutation| p permutation }
7053 * Returns a new Enumerator if no block given:
7056 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
7057 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7062 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
7066 n
= RARRAY_LEN(ary
); /* Array length */
7067 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
7069 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
7070 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
7072 if (r
< 0 || n
< r
) {
7073 /* no permutations: yield nothing */
7075 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7076 rb_yield(rb_ary_new2(0));
7078 else if (r
== 1) { /* this is a special, easy case */
7079 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7080 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7083 else { /* this is the general case */
7085 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
7086 char *used
= (char*)(p
+ r
);
7087 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7088 RBASIC_CLEAR_CLASS(ary0
);
7090 MEMZERO(used
, char, n
); /* initialize array */
7092 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
7094 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7100 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
7104 MEMZERO(stack
+1, long, n
);
7107 for (lev
++; lev
< n
; lev
++) {
7108 stack
[lev
+1] = stack
[lev
]+1;
7110 if (!yield_indexed_values(values
, n
, stack
+1)) {
7111 rb_raise(rb_eRuntimeError
, "combination reentered");
7114 if (lev
== 0) return;
7116 } while (stack
[lev
+1]+n
== len
+lev
+1);
7121 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7123 long n
= RARRAY_LEN(ary
);
7124 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7126 return binomial_coefficient(k
, n
);
7131 * combination(n) {|element| ... } -> self
7132 * combination(n) -> new_enumerator
7134 * When a block and a positive
7135 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7136 * argument +n+ (<tt>0 < n <= self.size</tt>)
7137 * are given, calls the block with all +n+-tuple combinations of +self+;
7140 * a = %w[a b c] # => ["a", "b", "c"]
7141 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7149 * The order of the yielded combinations is not guaranteed.
7151 * When +n+ is zero, calls the block once with a new empty array:
7153 * a.combination(0) {|combination| p combination }
7154 * [].combination(0) {|combination| p combination }
7161 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7162 * does not call the block:
7164 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7165 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7167 * With no block given, returns a new Enumerator.
7169 * Related: Array#permutation;
7170 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7174 rb_ary_combination(VALUE ary
, VALUE num
)
7179 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7180 len
= RARRAY_LEN(ary
);
7181 if (n
< 0 || len
< n
) {
7185 rb_yield(rb_ary_new2(0));
7188 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7189 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7193 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7195 long *stack
= ALLOCV_N(long, t0
, n
+1);
7197 RBASIC_CLEAR_CLASS(ary0
);
7198 combinate0(len
, n
, stack
, ary0
);
7200 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7206 * Compute repeated permutations of +r+ elements of the set
7207 * <code>[0..n-1]</code>.
7209 * When we have a complete repeated permutation of array indices, copy the
7210 * values at those indices into a new array and yield that array.
7212 * n: the size of the set
7213 * r: the number of elements in each permutation
7214 * p: the array (of size r) that we're filling in
7215 * values: the Ruby array that holds the actual values to permute
7218 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7220 long i
= 0, index
= 0;
7224 if (++index
< r
-1) {
7228 for (i
= 0; i
< n
; ++i
) {
7230 if (!yield_indexed_values(values
, r
, p
)) {
7231 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7235 if (index
<= 0) return;
7236 } while ((i
= ++p
[--index
]) >= n
);
7241 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7243 long n
= RARRAY_LEN(ary
);
7244 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7250 return LONG2FIX(!k
);
7252 return rb_int_positive_pow(n
, (unsigned long)k
);
7257 * array.repeated_permutation(n) {|permutation| ... } -> self
7258 * array.repeated_permutation(n) -> new_enumerator
7260 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7261 * each permutation is an +Array+;
7262 * returns +self+. The order of the permutations is indeterminate.
7264 * When a block and a positive Integer argument +n+ are given, calls the block with each
7265 * +n+-tuple repeated permutation of the elements of +self+.
7266 * The number of permutations is <tt>self.size**n</tt>.
7271 * a.repeated_permutation(1) {|permutation| p permutation }
7281 * a.repeated_permutation(2) {|permutation| p permutation }
7295 * If +n+ is zero, calls the block once with an empty +Array+.
7297 * If +n+ is negative, does not call the block:
7299 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7301 * Returns a new Enumerator if no block given:
7304 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7306 * Using Enumerators, it's convenient to show the permutations and counts
7307 * for some values of +n+:
7309 * e = a.repeated_permutation(0)
7312 * e = a.repeated_permutation(1)
7314 * e.to_a # => [[0], [1], [2]]
7315 * e = a.repeated_permutation(2)
7317 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7321 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7325 n
= RARRAY_LEN(ary
); /* Array length */
7326 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7327 r
= NUM2LONG(num
); /* Permutation size from argument */
7330 /* no permutations: yield nothing */
7332 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7333 rb_yield(rb_ary_new2(0));
7335 else if (r
== 1) { /* this is a special, easy case */
7336 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7337 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7340 else { /* this is the general case */
7342 long *p
= ALLOCV_N(long, t0
, r
);
7343 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7344 RBASIC_CLEAR_CLASS(ary0
);
7346 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7348 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7354 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7356 long i
= 0, index
= 0;
7360 if (++index
< r
-1) {
7364 for (; i
< n
; ++i
) {
7366 if (!yield_indexed_values(values
, r
, p
)) {
7367 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7371 if (index
<= 0) return;
7372 } while ((i
= ++p
[--index
]) >= n
);
7377 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7379 long n
= RARRAY_LEN(ary
);
7380 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7384 return binomial_coefficient(k
, n
+ k
- 1);
7389 * array.repeated_combination(n) {|combination| ... } -> self
7390 * array.repeated_combination(n) -> new_enumerator
7392 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7393 * each combination is an +Array+;
7394 * returns +self+. The order of the combinations is indeterminate.
7396 * When a block and a positive Integer argument +n+ are given, calls the block with each
7397 * +n+-tuple repeated combination of the elements of +self+.
7398 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7403 * a.repeated_combination(1) {|combination| p combination }
7413 * a.repeated_combination(2) {|combination| p combination }
7424 * If +n+ is zero, calls the block once with an empty +Array+.
7426 * If +n+ is negative, does not call the block:
7428 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7430 * Returns a new Enumerator if no block given:
7433 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7435 * Using Enumerators, it's convenient to show the combinations and counts
7436 * for some values of +n+:
7438 * e = a.repeated_combination(0)
7441 * e = a.repeated_combination(1)
7443 * e.to_a # => [[0], [1], [2]]
7444 * e = a.repeated_combination(2)
7446 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7451 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7455 n
= NUM2LONG(num
); /* Combination size from argument */
7456 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7457 len
= RARRAY_LEN(ary
);
7462 rb_yield(rb_ary_new2(0));
7465 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7466 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7469 else if (len
== 0) {
7474 long *p
= ALLOCV_N(long, t0
, n
);
7475 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7476 RBASIC_CLEAR_CLASS(ary0
);
7478 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7480 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7487 * array.product(*other_arrays) -> new_array
7488 * array.product(*other_arrays) {|combination| ... } -> self
7490 * Computes and returns or yields all combinations of elements from all the Arrays,
7491 * including both +self+ and +other_arrays+:
7493 * - The number of combinations is the product of the sizes of all the arrays,
7494 * including both +self+ and +other_arrays+.
7495 * - The order of the returned combinations is indeterminate.
7497 * When no block is given, returns the combinations as an +Array+ of Arrays:
7503 * p.size # => 6 # a.size * a1.size
7504 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7505 * p = a.product(a1, a2)
7506 * p.size # => 12 # a.size * a1.size * a2.size
7507 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7509 * If any argument is an empty +Array+, returns an empty +Array+.
7511 * If no argument is given, returns an +Array+ of 1-element Arrays,
7512 * each containing an element of +self+:
7514 * a.product # => [[0], [1], [2]]
7516 * When a block is given, yields each combination as an +Array+; returns +self+:
7518 * a.product(a1) {|combination| p combination }
7529 * If any argument is an empty +Array+, does not call the block:
7531 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7533 * If no argument is given, yields each element of +self+ as a 1-element +Array+:
7535 * a.product {|combination| p combination }
7546 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7548 int n
= argc
+1; /* How many arrays we're operating on */
7549 volatile VALUE t0
= rb_ary_hidden_new(n
);
7550 volatile VALUE t1
= Qundef
;
7551 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7552 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7553 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7557 RBASIC_CLEAR_CLASS(t0
);
7559 /* initialize the arrays of arrays */
7562 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7563 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7565 /* initialize the counters for the arrays */
7566 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7568 /* Otherwise, allocate and fill in an array of results */
7569 if (rb_block_given_p()) {
7570 /* Make defensive copies of arrays; exit if any is empty */
7571 for (i
= 0; i
< n
; i
++) {
7572 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7573 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7577 /* Compute the length of the result array; return [] if any is empty */
7578 for (i
= 0; i
< n
; i
++) {
7579 long k
= RARRAY_LEN(arrays
[i
]);
7581 result
= rb_ary_new2(0);
7584 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7585 rb_raise(rb_eRangeError
, "too big to product");
7588 result
= rb_ary_new2(resultlen
);
7592 /* fill in one subarray */
7593 VALUE subarray
= rb_ary_new2(n
);
7594 for (j
= 0; j
< n
; j
++) {
7595 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7598 /* put it on the result array */
7599 if (NIL_P(result
)) {
7600 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7602 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7603 rb_raise(rb_eRuntimeError
, "product reentered");
7606 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7610 rb_ary_push(result
, subarray
);
7614 * Increment the last counter. If it overflows, reset to 0
7615 * and increment the one before it.
7619 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7621 /* If the first counter overflows, we are done */
7622 if (--m
< 0) goto done
;
7630 return NIL_P(result
) ? ary
: result
;
7635 * array.take(n) -> new_array
7637 * Returns a new +Array+ containing the first +n+ element of +self+,
7638 * where +n+ is a non-negative Integer;
7639 * does not modify +self+.
7643 * a = [0, 1, 2, 3, 4, 5]
7644 * a.take(1) # => [0]
7645 * a.take(2) # => [0, 1]
7646 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7647 * a # => [0, 1, 2, 3, 4, 5]
7652 rb_ary_take(VALUE obj
, VALUE n
)
7654 long len
= NUM2LONG(n
);
7656 rb_raise(rb_eArgError
, "attempt to take negative size");
7658 return rb_ary_subseq(obj
, 0, len
);
7663 * array.take_while {|element| ... } -> new_array
7664 * array.take_while -> new_enumerator
7666 * Returns a new +Array+ containing zero or more leading elements of +self+;
7667 * does not modify +self+.
7669 * With a block given, calls the block with each successive element of +self+;
7670 * stops if the block returns +false+ or +nil+;
7671 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7673 * a = [0, 1, 2, 3, 4, 5]
7674 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7675 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7676 * a # => [0, 1, 2, 3, 4, 5]
7678 * With no block given, returns a new Enumerator:
7680 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7685 rb_ary_take_while(VALUE ary
)
7689 RETURN_ENUMERATOR(ary
, 0, 0);
7690 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7691 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7693 return rb_ary_take(ary
, LONG2FIX(i
));
7698 * drop(n) -> new_array
7700 * Returns a new array containing all but the first +n+ element of +self+,
7701 * where +n+ is a non-negative Integer;
7702 * does not modify +self+.
7706 * a = [0, 1, 2, 3, 4, 5]
7707 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7708 * a.drop(1) # => [1, 2, 3, 4, 5]
7709 * a.drop(2) # => [2, 3, 4, 5]
7712 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7716 rb_ary_drop(VALUE ary
, VALUE n
)
7719 long pos
= NUM2LONG(n
);
7721 rb_raise(rb_eArgError
, "attempt to drop negative size");
7724 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7725 if (NIL_P(result
)) result
= rb_ary_new();
7731 * drop_while {|element| ... } -> new_array
7732 * drop_while -> new_enumerator
7734 * With a block given, calls the block with each successive element of +self+;
7735 * stops if the block returns +false+ or +nil+;
7736 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7737 * does not modify +self+:
7739 * a = [0, 1, 2, 3, 4, 5]
7740 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7742 * With no block given, returns a new Enumerator.
7744 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7748 rb_ary_drop_while(VALUE ary
)
7752 RETURN_ENUMERATOR(ary
, 0, 0);
7753 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7754 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7756 return rb_ary_drop(ary
, LONG2FIX(i
));
7761 * any? -> true or false
7762 * any?(object) -> true or false
7763 * any? {|element| ... } -> true or false
7765 * Returns whether for any element of +self+, a given criterion is satisfied.
7767 * With no block and no argument, returns whether any element of +self+ is truthy:
7769 * [nil, false, []].any? # => true # Array object is truthy.
7770 * [nil, false, {}].any? # => true # Hash object is truthy.
7771 * [nil, false, ''].any? # => true # String object is truthy.
7772 * [nil, false].any? # => false # Nil and false are not truthy.
7774 * With argument +object+ given,
7775 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7777 * [nil, false, 0].any?(0) # => true
7778 * [nil, false, 1].any?(0) # => false
7779 * [nil, false, 'food'].any?(/foo/) # => true
7780 * [nil, false, 'food'].any?(/bar/) # => false
7782 * With a block given,
7783 * calls the block with each element in +self+;
7784 * returns whether the block returns any truthy value:
7786 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7787 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7789 * With both a block and argument +object+ given,
7790 * ignores the block and uses +object+ as above.
7792 * <b>Special case</b>: returns +false+ if +self+ is empty
7793 * (regardless of any given argument or block).
7795 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7799 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7801 long i
, len
= RARRAY_LEN(ary
);
7803 rb_check_arity(argc
, 0, 1);
7804 if (!len
) return Qfalse
;
7806 if (rb_block_given_p()) {
7807 rb_warn("given block not used");
7809 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7810 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7813 else if (!rb_block_given_p()) {
7814 for (i
= 0; i
< len
; ++i
) {
7815 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7819 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7820 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7828 * all? -> true or false
7829 * all?(object) -> true or false
7830 * all? {|element| ... } -> true or false
7832 * Returns whether for every element of +self+,
7833 * a given criterion is satisfied.
7835 * With no block and no argument,
7836 * returns whether every element of +self+ is truthy:
7838 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7839 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7840 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7842 * With argument +object+ given, returns whether <tt>object === ele</tt>
7843 * for every element +ele+ in +self+:
7845 * [0, 0, 0].all?(0) # => true
7846 * [0, 1, 2].all?(1) # => false
7847 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7848 * ['food', 'drink'].all?(/foo/) # => false
7850 * With a block given, calls the block with each element in +self+;
7851 * returns whether the block returns only truthy values:
7853 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7854 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7856 * With both a block and argument +object+ given,
7857 * ignores the block and uses +object+ as above.
7859 * <b>Special case</b>: returns +true+ if +self+ is empty
7860 * (regardless of any given argument or block).
7862 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7866 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7868 long i
, len
= RARRAY_LEN(ary
);
7870 rb_check_arity(argc
, 0, 1);
7871 if (!len
) return Qtrue
;
7873 if (rb_block_given_p()) {
7874 rb_warn("given block not used");
7876 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7877 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7880 else if (!rb_block_given_p()) {
7881 for (i
= 0; i
< len
; ++i
) {
7882 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7886 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7887 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7895 * array.none? -> true or false
7896 * array.none? {|element| ... } -> true or false
7897 * array.none?(obj) -> true or false
7899 * Returns +true+ if no element of +self+ meet a given criterion.
7901 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7902 * +false+ otherwise:
7904 * [nil, false].none? # => true
7905 * [nil, 0, false].none? # => false
7906 * [].none? # => true
7908 * With a block given and no argument, calls the block with each element in +self+;
7909 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7911 * [0, 1, 2].none? {|element| element > 3 } # => true
7912 * [0, 1, 2].none? {|element| element > 1 } # => false
7914 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7916 * ['food', 'drink'].none?(/bar/) # => true
7917 * ['food', 'drink'].none?(/foo/) # => false
7918 * [].none?(/foo/) # => true
7919 * [0, 1, 2].none?(3) # => true
7920 * [0, 1, 2].none?(1) # => false
7922 * Related: Enumerable#none?
7926 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7928 long i
, len
= RARRAY_LEN(ary
);
7930 rb_check_arity(argc
, 0, 1);
7931 if (!len
) return Qtrue
;
7933 if (rb_block_given_p()) {
7934 rb_warn("given block not used");
7936 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7937 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7940 else if (!rb_block_given_p()) {
7941 for (i
= 0; i
< len
; ++i
) {
7942 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7946 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7947 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7955 * array.one? -> true or false
7956 * array.one? {|element| ... } -> true or false
7957 * array.one?(obj) -> true or false
7959 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7961 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7962 * +false+ otherwise:
7964 * [nil, 0].one? # => true
7965 * [0, 0].one? # => false
7966 * [nil, nil].one? # => false
7967 * [].one? # => false
7969 * With a block given and no argument, calls the block with each element in +self+;
7970 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7972 * [0, 1, 2].one? {|element| element > 0 } # => false
7973 * [0, 1, 2].one? {|element| element > 1 } # => true
7974 * [0, 1, 2].one? {|element| element > 2 } # => false
7976 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7977 * +false+ otherwise:
7979 * [0, 1, 2].one?(0) # => true
7980 * [0, 0, 1].one?(0) # => false
7981 * [1, 1, 2].one?(0) # => false
7982 * ['food', 'drink'].one?(/bar/) # => false
7983 * ['food', 'drink'].one?(/foo/) # => true
7984 * [].one?(/foo/) # => false
7986 * Related: Enumerable#one?
7990 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7992 long i
, len
= RARRAY_LEN(ary
);
7993 VALUE result
= Qfalse
;
7995 rb_check_arity(argc
, 0, 1);
7996 if (!len
) return Qfalse
;
7998 if (rb_block_given_p()) {
7999 rb_warn("given block not used");
8001 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
8002 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
8003 if (result
) return Qfalse
;
8008 else if (!rb_block_given_p()) {
8009 for (i
= 0; i
< len
; ++i
) {
8010 if (RTEST(RARRAY_AREF(ary
, i
))) {
8011 if (result
) return Qfalse
;
8017 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
8018 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
8019 if (result
) return Qfalse
;
8029 * array.dig(index, *identifiers) -> object
8031 * Finds and returns the object in nested object
8032 * specified by +index+ and +identifiers+;
8033 * the nested objects may be instances of various classes.
8034 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8038 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8039 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8040 * a.dig(1, 2) # => [:bat, :bam]
8041 * a.dig(1, 2, 0) # => :bat
8042 * a.dig(1, 2, 3) # => nil
8044 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8048 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
8050 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
8051 self
= rb_ary_at(self
, *argv
);
8052 if (!--argc
) return self
;
8054 return rb_obj_dig(argc
, argv
, self
, Qnil
);
8058 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
8061 v
= rb_fix_plus(LONG2FIX(n
), v
);
8063 v
= rb_rational_plus(r
, v
);
8066 v
= rb_fix_plus(LONG2FIX(0), v
);
8073 * array.sum(init = 0) -> object
8074 * array.sum(init = 0) {|element| ... } -> object
8076 * When no block is given, returns the object equivalent to:
8079 * array.each {|element| sum += element }
8082 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
8088 * a.sum(100) # => 106
8090 * The elements need not be numeric, but must be <tt>+</tt>-compatible
8091 * with each other and with +init+:
8093 * a = ['abc', 'def', 'ghi']
8094 * a.sum('jkl') # => "jklabcdefghi"
8096 * When a block is given, it is called with each element
8097 * and the block's return value (instead of the element itself) is used as the addend:
8099 * a = ['zero', 1, :two]
8100 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
8101 * s # => "Coerced and concatenated: zero1two"
8105 * - Array#join and Array#flatten may be faster than Array#sum
8106 * for an +Array+ of Strings or an +Array+ of Arrays.
8107 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8112 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
8118 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
8120 block_given
= rb_block_given_p();
8122 if (RARRAY_LEN(ary
) == 0)
8128 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
8130 goto init_is_a_value
;
8133 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
8134 e
= RARRAY_AREF(ary
, i
);
8138 n
+= FIX2LONG(e
); /* should not overflow long type */
8140 v
= rb_big_plus(LONG2NUM(n
), v
);
8144 else if (RB_BIGNUM_TYPE_P(e
))
8145 v
= rb_big_plus(e
, v
);
8146 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8150 r
= rb_rational_plus(r
, e
);
8155 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8159 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8161 if (RB_FLOAT_TYPE_P(e
)) {
8163 * Kahan-Babuska balancing compensated summation algorithm
8164 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8171 goto has_float_value
;
8172 for (; i
< RARRAY_LEN(ary
); i
++) {
8173 e
= RARRAY_AREF(ary
, i
);
8176 if (RB_FLOAT_TYPE_P(e
))
8178 x
= RFLOAT_VALUE(e
);
8179 else if (FIXNUM_P(e
))
8181 else if (RB_BIGNUM_TYPE_P(e
))
8183 else if (RB_TYPE_P(e
, T_RATIONAL
))
8188 if (isnan(f
)) continue;
8194 if (isinf(f
) && signbit(x
) != signbit(f
))
8200 if (isinf(f
)) continue;
8203 if (fabs(f
) >= fabs(x
))
8216 goto has_some_value
;
8218 for (; i
< RARRAY_LEN(ary
); i
++) {
8219 e
= RARRAY_AREF(ary
, i
);
8223 v
= rb_funcall(v
, idPLUS
, 1, e
);
8230 rb_ary_deconstruct(VALUE ary
)
8236 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8237 * Any object (even another array) may be an array element,
8238 * and an array can contain objects of different types.
8240 * == +Array+ Indexes
8242 * +Array+ indexing starts at 0, as in C or Java.
8244 * A positive index is an offset from the first element:
8246 * - Index 0 indicates the first element.
8247 * - Index 1 indicates the second element.
8250 * A negative index is an offset, backwards, from the end of the array:
8252 * - Index -1 indicates the last element.
8253 * - Index -2 indicates the next-to-last element.
8256 * A non-negative index is <i>in range</i> if and only if it is smaller than
8257 * the size of the array. For a 3-element array:
8259 * - Indexes 0 through 2 are in range.
8260 * - Index 3 is out of range.
8262 * A negative index is <i>in range</i> if and only if its absolute value is
8263 * not larger than the size of the array. For a 3-element array:
8265 * - Indexes -1 through -3 are in range.
8266 * - Index -4 is out of range.
8268 * Although the effective index into an array is always an integer,
8269 * some methods (both within and outside of class +Array+)
8270 * accept one or more non-integer arguments that are
8271 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8274 * == Creating Arrays
8276 * You can create an +Array+ object explicitly with:
8278 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8280 * [1, 'one', :one, [2, 'two', :two]]
8282 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8284 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8285 * %w[1 % *] # => ["1", "%", "*"]
8287 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8289 * %i[foo bar baz] # => [:foo, :bar, :baz]
8290 * %i[1 % *] # => [:"1", :%, :*]
8292 * - \Method Kernel#Array:
8294 * Array(["a", "b"]) # => ["a", "b"]
8295 * Array(1..5) # => [1, 2, 3, 4, 5]
8296 * Array(key: :value) # => [[:key, :value]]
8297 * Array(nil) # => []
8299 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8301 * - \Method Array.new:
8304 * Array.new(3) # => [nil, nil, nil]
8305 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8306 * Array.new(3, true) # => [true, true, true]
8308 * Note that the last example above populates the array
8309 * with references to the same object.
8310 * This is recommended only in cases where that object is a natively immutable object
8311 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8313 * Another way to create an array with various objects, using a block;
8314 * this usage is safe for mutable objects such as hashes, strings or
8317 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8319 * Here is a way to create a multi-dimensional array:
8321 * Array.new(3) {Array.new(3)}
8322 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8324 * A number of Ruby methods, both in the core and in the standard library,
8325 * provide instance method +to_a+, which converts an object to an array.
8333 * - OptionParser#to_a
8338 * - Benchmark::Tms#to_a
8340 * - Enumerator::Lazy#to_a
8342 * - Gem::NameTuple#to_a
8343 * - Gem::Platform#to_a
8344 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8345 * - Gem::SourceList#to_a
8346 * - OpenSSL::X509::Extension#to_a
8347 * - OpenSSL::X509::Name#to_a
8349 * - Rinda::RingFinger#to_a
8350 * - Ripper::Lexer::Elem#to_a
8351 * - RubyVM::InstructionSequence#to_a
8356 * In addition to the methods it mixes in through the Enumerable module, the
8357 * +Array+ class has proprietary methods for accessing, searching and otherwise
8358 * manipulating arrays.
8360 * Some of the more common ones are illustrated below.
8362 * == Accessing Elements
8364 * Elements in an array can be retrieved using the Array#[] method. It can
8365 * take a single integer argument (a numeric index), a pair of arguments
8366 * (start and length) or a range. Negative indices start counting from the end,
8367 * with -1 being the last element.
8369 * arr = [1, 2, 3, 4, 5, 6]
8373 * arr[2, 3] #=> [3, 4, 5]
8374 * arr[1..4] #=> [2, 3, 4, 5]
8375 * arr[1..-3] #=> [2, 3, 4]
8377 * Another way to access a particular array element is by using the #at method
8381 * The #slice method works in an identical manner to Array#[].
8383 * To raise an error for indices outside of the array bounds or else to
8384 * provide a default value when that happens, you can use #fetch.
8386 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8387 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8388 * arr.fetch(100, "oops") #=> "oops"
8390 * The special methods #first and #last will return the first and last
8391 * elements of an array, respectively.
8396 * To return the first +n+ elements of an array, use #take
8398 * arr.take(3) #=> [1, 2, 3]
8400 * #drop does the opposite of #take, by returning the elements after +n+
8401 * elements have been dropped:
8403 * arr.drop(3) #=> [4, 5, 6]
8405 * == Obtaining Information about an +Array+
8407 * Arrays keep track of their own length at all times. To query an array
8408 * about the number of elements it contains, use #length, #count or #size.
8410 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8411 * browsers.length #=> 5
8412 * browsers.count #=> 5
8414 * To check whether an array contains any elements at all
8416 * browsers.empty? #=> false
8418 * To check whether a particular item is included in the array
8420 * browsers.include?('Konqueror') #=> false
8422 * == Adding Items to Arrays
8424 * Items can be added to the end of an array by using either #push or #<<
8426 * arr = [1, 2, 3, 4]
8427 * arr.push(5) #=> [1, 2, 3, 4, 5]
8428 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8430 * #unshift will add a new item to the beginning of an array.
8432 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8434 * With #insert you can add a new element to an array at any position.
8436 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8438 * Using the #insert method, you can also insert multiple values at once:
8440 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8441 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8443 * == Removing Items from an +Array+
8445 * The method #pop removes the last element in an array and returns it:
8447 * arr = [1, 2, 3, 4, 5, 6]
8449 * arr #=> [1, 2, 3, 4, 5]
8451 * To retrieve and at the same time remove the first item, use #shift:
8454 * arr #=> [2, 3, 4, 5]
8456 * To delete an element at a particular index:
8458 * arr.delete_at(2) #=> 4
8461 * To delete a particular element anywhere in an array, use #delete:
8463 * arr = [1, 2, 2, 3]
8464 * arr.delete(2) #=> 2
8467 * A useful method if you need to remove +nil+ values from an array is
8470 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8471 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8472 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8473 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8474 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8476 * Another common need is to remove duplicate elements from an array.
8478 * It has the non-destructive #uniq, and destructive method #uniq!
8480 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8481 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8483 * == Iterating over Arrays
8485 * Like all classes that include the Enumerable module, +Array+ has an each
8486 * method, which defines what elements should be iterated over and how. In
8487 * case of Array's #each, all elements in the +Array+ instance are yielded to
8488 * the supplied block in sequence.
8490 * Note that this operation leaves the array unchanged.
8492 * arr = [1, 2, 3, 4, 5]
8493 * arr.each {|a| print a -= 10, " "}
8494 * # prints: -9 -8 -7 -6 -5
8495 * #=> [1, 2, 3, 4, 5]
8497 * Another sometimes useful iterator is #reverse_each which will iterate over
8498 * the elements in the array in reverse order.
8500 * words = %w[first second third fourth fifth sixth]
8502 * words.reverse_each {|word| str += "#{word} "}
8503 * p str #=> "sixth fifth fourth third second first "
8505 * The #map method can be used to create a new array based on the original
8506 * array, but with the values modified by the supplied block:
8508 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8509 * arr #=> [1, 2, 3, 4, 5]
8510 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8511 * arr #=> [1, 4, 9, 16, 25]
8514 * == Selecting Items from an +Array+
8516 * Elements can be selected from an array according to criteria defined in a
8517 * block. The selection can happen in a destructive or a non-destructive
8518 * manner. While the destructive operations will modify the array they were
8519 * called on, the non-destructive methods usually return a new array with the
8520 * selected elements, but leave the original array unchanged.
8522 * === Non-destructive Selection
8524 * arr = [1, 2, 3, 4, 5, 6]
8525 * arr.select {|a| a > 3} #=> [4, 5, 6]
8526 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8527 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8528 * arr #=> [1, 2, 3, 4, 5, 6]
8530 * === Destructive Selection
8532 * #select! and #reject! are the corresponding destructive methods to #select
8535 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8536 * opposite result when supplied with the same block:
8538 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8541 * arr = [1, 2, 3, 4, 5, 6]
8542 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8547 * First, what's elsewhere. \Class +Array+:
8549 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8550 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8551 * which provides dozens of additional methods.
8553 * Here, class +Array+ provides methods that are useful for:
8555 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8556 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8557 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8558 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8559 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8560 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8561 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8562 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8563 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8564 * - {And more....}[rdoc-ref:Array@Other+Methods]
8566 * === Methods for Creating an +Array+
8568 * - ::[]: Returns a new array populated with given objects.
8569 * - ::new: Returns a new array.
8570 * - ::try_convert: Returns a new array created from a given object.
8572 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8574 * === Methods for Querying
8576 * - #length (aliased as #size): Returns the count of elements.
8577 * - #include?: Returns whether any element <tt>==</tt> a given object.
8578 * - #empty?: Returns whether there are no elements.
8579 * - #all?: Returns whether all elements meet a given criterion.
8580 * - #any?: Returns whether any element meets a given criterion.
8581 * - #none?: Returns whether no element <tt>==</tt> a given object.
8582 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8583 * - #count: Returns the count of elements that meet a given criterion.
8584 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8585 * - #rindex: Returns the index of the last element that meets a given criterion.
8586 * - #hash: Returns the integer hash code.
8588 * === Methods for Comparing
8590 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8591 * greater than a given object.
8592 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8593 * in a given object.
8594 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8595 * element in a given object.
8597 * === Methods for Fetching
8599 * These methods do not modify +self+.
8601 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8602 * - #fetch: Returns the element at a given offset.
8603 * - #first: Returns one or more leading elements.
8604 * - #last: Returns one or more trailing elements.
8605 * - #max: Returns one or more maximum-valued elements,
8606 * as determined by <tt><=></tt> or a given block.
8607 * - #min: Returns one or more minimum-valued elements,
8608 * as determined by <tt><=></tt> or a given block.
8609 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8610 * as determined by <tt><=></tt> or a given block.
8611 * - #assoc: Returns the first element that is an array
8612 * whose first element <tt>==</tt> a given object.
8613 * - #rassoc: Returns the first element that is an array
8614 * whose second element <tt>==</tt> a given object.
8615 * - #at: Returns the element at a given offset.
8616 * - #values_at: Returns the elements at given offsets.
8617 * - #dig: Returns the object in nested objects
8618 * that is specified by a given index and additional arguments.
8619 * - #drop: Returns trailing elements as determined by a given index.
8620 * - #take: Returns leading elements as determined by a given index.
8621 * - #drop_while: Returns trailing elements as determined by a given block.
8622 * - #take_while: Returns leading elements as determined by a given block.
8623 * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
8624 * - #reverse: Returns all elements in reverse order.
8625 * - #compact: Returns an array containing all non-+nil+ elements.
8626 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8627 * - #uniq: Returns an array containing non-duplicate elements.
8628 * - #rotate: Returns all elements with some rotated from one end to the other.
8629 * - #bsearch: Returns an element selected via a binary search
8630 * as determined by a given block.
8631 * - #bsearch_index: Returns the index of an element selected via a binary search
8632 * as determined by a given block.
8633 * - #sample: Returns one or more random elements.
8634 * - #shuffle: Returns elements in a random order.
8636 * === Methods for Assigning
8638 * These methods add, replace, or reorder elements in +self+.
8640 * - #[]=: Assigns specified elements with a given object.
8641 * - #<<: Appends an element.
8642 * - #push (aliased as #append): Appends elements.
8643 * - #unshift (aliased as #prepend): Prepends leading elements.
8644 * - #insert: Inserts given objects at a given offset; does not replace elements.
8645 * - #concat: Appends all elements from given arrays.
8646 * - #fill: Replaces specified elements with specified objects.
8647 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8648 * - #reverse!: Replaces +self+ with its elements reversed.
8649 * - #rotate!: Replaces +self+ with its elements rotated.
8650 * - #shuffle!: Replaces +self+ with its elements in random order.
8651 * - #sort!: Replaces +self+ with its elements sorted,
8652 * as determined by <tt><=></tt> or a given block.
8653 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8655 * === Methods for Deleting
8657 * Each of these methods removes elements from +self+:
8659 * - #pop: Removes and returns the last element.
8660 * - #shift: Removes and returns the first element.
8661 * - #compact!: Removes all +nil+ elements.
8662 * - #delete: Removes elements equal to a given object.
8663 * - #delete_at: Removes the element at a given offset.
8664 * - #delete_if: Removes elements specified by a given block.
8665 * - #clear: Removes all elements.
8666 * - #keep_if: Removes elements not specified by a given block.
8667 * - #reject!: Removes elements specified by a given block.
8668 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8669 * - #slice!: Removes and returns a sequence of elements.
8670 * - #uniq!: Removes duplicates.
8672 * === Methods for Combining
8674 * - #&: Returns an array containing elements found both in +self+ and a given array.
8675 * - #intersection: Returns an array containing elements found both in +self+
8676 * and in each given array.
8677 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8678 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8679 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8680 * duplicates removed.
8681 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8682 * duplicates removed.
8683 * - #difference: Returns an array containing all elements of +self+ that are not found
8684 * in any of the given arrays..
8685 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8687 * === Methods for Iterating
8689 * - #each: Passes each element to a given block.
8690 * - #reverse_each: Passes each element, in reverse order, to a given block.
8691 * - #each_index: Passes each element index to a given block.
8692 * - #cycle: Calls a given block with each element, then does so again,
8693 * for a specified number of times, or forever.
8694 * - #combination: Calls a given block with combinations of elements of +self+;
8695 * a combination does not use the same element more than once.
8696 * - #permutation: Calls a given block with permutations of elements of +self+;
8697 * a permutation does not use the same element more than once.
8698 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8699 * a combination may use the same element more than once.
8700 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8701 * a permutation may use the same element more than once.
8703 * === Methods for Converting
8705 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8706 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8707 * - #flatten: Returns an array that is a recursive flattening of +self+.
8708 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8709 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8710 * - #join: Returns a newsString containing the elements joined by the field separator.
8711 * - #to_a: Returns +self+ or a new array containing all elements.
8712 * - #to_ary: Returns +self+.
8713 * - #to_h: Returns a new hash formed from the elements.
8714 * - #transpose: Transposes +self+, which must be an array of arrays.
8715 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8716 * follow the link for details.
8720 * - #*: Returns one of the following:
8722 * - With integer argument +n+, a new array that is the concatenation
8723 * of +n+ copies of +self+.
8724 * - With string argument +field_separator+, a new string that is equivalent to
8725 * <tt>join(field_separator)</tt>.
8727 * - #pack: Packs the elements into a binary sequence.
8728 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8734 fake_ary_flags
= init_fake_ary_flags();
8736 rb_cArray
= rb_define_class("Array", rb_cObject
);
8737 rb_include_module(rb_cArray
, rb_mEnumerable
);
8739 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8740 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8741 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8742 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8743 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8744 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8746 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8747 rb_define_alias(rb_cArray
, "to_s", "inspect");
8748 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8749 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8750 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8752 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8753 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8754 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8756 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8757 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8758 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8759 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8760 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8761 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8762 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8763 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8764 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8765 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8766 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8767 rb_define_alias(rb_cArray
, "append", "push");
8768 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8769 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8770 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8771 rb_define_alias(rb_cArray
, "prepend", "unshift");
8772 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8773 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8774 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8775 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8776 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8777 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8778 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8779 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8780 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8781 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8782 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8783 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8784 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8785 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8786 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8787 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8788 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8789 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8790 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8791 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8792 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8793 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8794 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8795 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8796 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8797 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8798 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8799 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8800 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8801 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8802 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8803 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8804 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8805 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8806 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8807 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8808 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8809 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8810 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8812 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8813 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8815 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8816 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8818 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8819 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8821 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8822 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8823 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8825 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8826 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8827 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8829 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8830 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8831 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8832 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8833 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8834 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8835 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8836 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8837 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8838 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8839 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8840 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8841 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8843 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8844 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8845 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8846 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8847 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8848 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8849 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8850 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8851 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8852 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8853 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8854 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8855 rb_define_method(rb_cArray
, "freeze", rb_ary_freeze
, 0);
8857 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8859 rb_cArray_empty_frozen
= rb_ary_freeze(rb_ary_new());
8860 rb_vm_register_global_object(rb_cArray_empty_frozen
);
8863 #include "array.rbinc"