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 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
46 * The array is shared. The buffer this array points to is owned by
47 * another array (the shared root).
48 * 1: RARRAY_EMBED_FLAG
49 * The array is embedded (its contents follow the header, rather than
50 * being on a separately allocated buffer).
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 */
267 #define ary_verify(ary) ((void)0)
271 rb_ary_ptr_use_start(VALUE ary
)
274 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
276 return (VALUE
*)RARRAY_CONST_PTR(ary
);
280 rb_ary_ptr_use_end(VALUE ary
)
283 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
288 rb_mem_clear(VALUE
*mem
, long size
)
296 ary_mem_clear(VALUE ary
, long beg
, long size
)
298 RARRAY_PTR_USE(ary
, ptr
, {
299 rb_mem_clear(ptr
+ beg
, size
);
304 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
312 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
314 RARRAY_PTR_USE(ary
, ptr
, {
315 memfill(ptr
+ beg
, size
, val
);
316 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
321 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
323 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary
));
325 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
326 rb_gc_writebarrier_remember(buff_owner_ary
);
327 RARRAY_PTR_USE(ary
, ptr
, {
328 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
333 RARRAY_PTR_USE(ary
, ptr
, {
334 for (i
=0; i
<argc
; i
++) {
335 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
342 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
344 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
348 ary_heap_alloc_buffer(size_t capa
)
350 return ALLOC_N(VALUE
, capa
);
354 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
356 ruby_sized_xfree((void *)ptr
, size
);
360 ary_heap_free(VALUE ary
)
362 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
366 ary_heap_realloc(VALUE ary
, size_t new_capa
)
368 RUBY_ASSERT(!OBJ_FROZEN(ary
));
369 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, ARY_HEAP_CAPA(ary
));
376 rb_ary_make_embedded(VALUE ary
)
378 RUBY_ASSERT(rb_ary_embeddable_p(ary
));
379 if (!ARY_EMBED_P(ary
)) {
380 const VALUE
*buf
= ARY_HEAP_PTR(ary
);
381 long len
= ARY_HEAP_LEN(ary
);
384 ARY_SET_EMBED_LEN(ary
, len
);
386 MEMCPY((void *)ARY_EMBED_PTR(ary
), (void *)buf
, VALUE
, len
);
388 ary_heap_free_ptr(ary
, buf
, len
* sizeof(VALUE
));
393 ary_resize_capa(VALUE ary
, long capacity
)
395 RUBY_ASSERT(RARRAY_LEN(ary
) <= capacity
);
396 RUBY_ASSERT(!OBJ_FROZEN(ary
));
397 RUBY_ASSERT(!ARY_SHARED_P(ary
));
399 if (capacity
> ary_embed_capa(ary
)) {
400 size_t new_capa
= capacity
;
401 if (ARY_EMBED_P(ary
)) {
402 long len
= ARY_EMBED_LEN(ary
);
403 VALUE
*ptr
= ary_heap_alloc_buffer(capacity
);
405 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
407 ARY_SET_PTR(ary
, ptr
);
408 ARY_SET_HEAP_LEN(ary
, len
);
411 new_capa
= ary_heap_realloc(ary
, capacity
);
413 ARY_SET_CAPA(ary
, new_capa
);
416 if (!ARY_EMBED_P(ary
)) {
417 long len
= ARY_HEAP_LEN(ary
);
418 long old_capa
= ARY_HEAP_CAPA(ary
);
419 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
421 if (len
> capacity
) len
= capacity
;
422 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
423 ary_heap_free_ptr(ary
, ptr
, old_capa
);
426 ARY_SET_LEN(ary
, len
);
434 ary_shrink_capa(VALUE ary
)
436 long capacity
= ARY_HEAP_LEN(ary
);
437 long old_capa
= ARY_HEAP_CAPA(ary
);
438 RUBY_ASSERT(!ARY_SHARED_P(ary
));
439 RUBY_ASSERT(old_capa
>= capacity
);
440 if (old_capa
> capacity
) {
441 size_t new_capa
= ary_heap_realloc(ary
, capacity
);
442 ARY_SET_CAPA(ary
, new_capa
);
449 ary_double_capa(VALUE ary
, long min
)
451 long new_capa
= ARY_CAPA(ary
) / 2;
453 if (new_capa
< ARY_DEFAULT_SIZE
) {
454 new_capa
= ARY_DEFAULT_SIZE
;
456 if (new_capa
>= ARY_MAX_SIZE
- min
) {
457 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
460 ary_resize_capa(ary
, new_capa
);
466 rb_ary_decrement_share(VALUE shared_root
)
468 if (!OBJ_FROZEN(shared_root
)) {
469 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
470 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
- 1);
475 rb_ary_unshare(VALUE ary
)
477 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
478 rb_ary_decrement_share(shared_root
);
479 FL_UNSET_SHARED(ary
);
483 rb_ary_reset(VALUE ary
)
485 if (ARY_OWNS_HEAP_P(ary
)) {
488 else if (ARY_SHARED_P(ary
)) {
493 ARY_SET_EMBED_LEN(ary
, 0);
497 rb_ary_increment_share(VALUE shared_root
)
499 if (!OBJ_FROZEN(shared_root
)) {
500 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
501 RUBY_ASSERT(num
>= 0);
502 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
508 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
510 RUBY_ASSERT(!ARY_EMBED_P(ary
));
511 RUBY_ASSERT(!OBJ_FROZEN(ary
));
512 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root
) || OBJ_FROZEN(shared_root
));
514 rb_ary_increment_share(shared_root
);
516 RB_OBJ_WRITE(ary
, &RARRAY(ary
)->as
.heap
.aux
.shared_root
, shared_root
);
518 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
522 rb_ary_modify_check(VALUE ary
)
524 rb_check_frozen(ary
);
529 rb_ary_cancel_sharing(VALUE ary
)
531 if (ARY_SHARED_P(ary
)) {
532 long shared_len
, len
= RARRAY_LEN(ary
);
533 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
535 ary_verify(shared_root
);
537 if (len
<= ary_embed_capa(ary
)) {
538 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
539 FL_UNSET_SHARED(ary
);
541 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
542 rb_ary_decrement_share(shared_root
);
543 ARY_SET_EMBED_LEN(ary
, len
);
545 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
546 long shift
= RARRAY_CONST_PTR(ary
) - RARRAY_CONST_PTR(shared_root
);
547 FL_UNSET_SHARED(ary
);
548 ARY_SET_PTR(ary
, RARRAY_CONST_PTR(shared_root
));
549 ARY_SET_CAPA(ary
, shared_len
);
550 RARRAY_PTR_USE(ary
, ptr
, {
551 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
553 FL_SET_EMBED(shared_root
);
554 rb_ary_decrement_share(shared_root
);
557 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
558 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
560 ARY_SET_CAPA(ary
, len
);
561 ARY_SET_PTR(ary
, ptr
);
564 rb_gc_writebarrier_remember(ary
);
570 rb_ary_modify(VALUE ary
)
572 rb_ary_modify_check(ary
);
573 rb_ary_cancel_sharing(ary
);
577 ary_ensure_room_for_push(VALUE ary
, long add_len
)
579 long old_len
= RARRAY_LEN(ary
);
580 long new_len
= old_len
+ add_len
;
583 if (old_len
> ARY_MAX_SIZE
- add_len
) {
584 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
586 if (ARY_SHARED_P(ary
)) {
587 if (new_len
> ary_embed_capa(ary
)) {
588 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
589 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
590 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
591 rb_ary_modify_check(ary
);
594 ary_verify(shared_root
);
598 /* if array is shared, then it is likely it participate in push/shift pattern */
600 capa
= ARY_CAPA(ary
);
601 if (new_len
> capa
- (capa
>> 6)) {
602 ary_double_capa(ary
, new_len
);
613 rb_ary_modify_check(ary
);
615 capa
= ARY_CAPA(ary
);
616 if (new_len
> capa
) {
617 ary_double_capa(ary
, new_len
);
628 * Freezes +self+ (if not already frozen); returns +self+:
631 * a.frozen? # => false
633 * a.frozen? # => true
635 * No further changes may be made to +self+;
636 * raises FrozenError if a change is attempted.
638 * Related: Kernel#frozen?.
642 rb_ary_freeze(VALUE ary
)
644 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
646 if (OBJ_FROZEN(ary
)) return ary
;
648 if (!ARY_EMBED_P(ary
) && !ARY_SHARED_P(ary
) && !ARY_SHARED_ROOT_P(ary
)) {
649 ary_shrink_capa(ary
);
652 return rb_obj_freeze(ary
);
655 /* This can be used to take a snapshot of an array (with
656 e.g. rb_ary_replace) and check later whether the array has been
657 modified from the snapshot. The snapshot is cheap, though if
658 something does modify the array it will pay the cost of copying
659 it. If Array#pop or Array#shift has been called, the array will
660 be still shared with the snapshot, but the array length will
663 rb_ary_shared_with_p(VALUE ary1
, VALUE ary2
)
665 if (!ARY_EMBED_P(ary1
) && ARY_SHARED_P(ary1
) &&
666 !ARY_EMBED_P(ary2
) && ARY_SHARED_P(ary2
) &&
667 ARY_SHARED_ROOT(ary1
) == ARY_SHARED_ROOT(ary2
) &&
668 ARY_HEAP_LEN(ary1
) == ARY_HEAP_LEN(ary2
)) {
675 ary_alloc_embed(VALUE klass
, long capa
)
677 size_t size
= ary_embed_size(capa
);
678 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
679 NEWOBJ_OF(ary
, struct RArray
, klass
,
680 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
683 * FL_SET_EMBED((VALUE)ary);
684 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
690 ary_alloc_heap(VALUE klass
)
692 NEWOBJ_OF(ary
, struct RArray
, klass
,
693 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
694 sizeof(struct RArray
), 0);
699 empty_ary_alloc(VALUE klass
)
701 RUBY_DTRACE_CREATE_HOOK(ARRAY
, 0);
702 return ary_alloc_embed(klass
, 0);
706 ary_new(VALUE klass
, long capa
)
711 rb_raise(rb_eArgError
, "negative array size (or size too big)");
713 if (capa
> ARY_MAX_SIZE
) {
714 rb_raise(rb_eArgError
, "array size too big");
717 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
719 if (ary_embeddable_p(capa
)) {
720 ary
= ary_alloc_embed(klass
, capa
);
723 ary
= ary_alloc_heap(klass
);
724 ARY_SET_CAPA(ary
, capa
);
725 RUBY_ASSERT(!ARY_EMBED_P(ary
));
727 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
728 ARY_SET_HEAP_LEN(ary
, 0);
735 rb_ary_new_capa(long capa
)
737 return ary_new(rb_cArray
, capa
);
743 return rb_ary_new_capa(0);
747 (rb_ary_new_from_args
)(long n
, ...)
753 ary
= rb_ary_new2(n
);
756 for (i
=0; i
<n
; i
++) {
757 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
766 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
770 ary
= ary_new(klass
, n
);
772 ary_memcpy(ary
, 0, n
, elts
);
780 rb_ary_new_from_values(long n
, const VALUE
*elts
)
782 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
786 ec_ary_alloc_embed(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
788 size_t size
= ary_embed_size(capa
);
789 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
790 NEWOBJ_OF(ary
, struct RArray
, klass
,
791 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
794 * FL_SET_EMBED((VALUE)ary);
795 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
801 ec_ary_alloc_heap(rb_execution_context_t
*ec
, VALUE klass
)
803 NEWOBJ_OF(ary
, struct RArray
, klass
,
804 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
805 sizeof(struct RArray
), ec
);
810 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
815 rb_raise(rb_eArgError
, "negative array size (or size too big)");
817 if (capa
> ARY_MAX_SIZE
) {
818 rb_raise(rb_eArgError
, "array size too big");
821 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
823 if (ary_embeddable_p(capa
)) {
824 ary
= ec_ary_alloc_embed(ec
, klass
, capa
);
827 ary
= ec_ary_alloc_heap(ec
, klass
);
828 ARY_SET_CAPA(ary
, capa
);
829 RUBY_ASSERT(!ARY_EMBED_P(ary
));
831 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
832 ARY_SET_HEAP_LEN(ary
, 0);
839 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
843 ary
= ec_ary_new(ec
, rb_cArray
, n
);
845 ary_memcpy(ary
, 0, n
, elts
);
853 rb_ary_hidden_new(long capa
)
855 VALUE ary
= ary_new(0, capa
);
860 rb_ary_hidden_new_fill(long capa
)
862 VALUE ary
= rb_ary_hidden_new(capa
);
863 ary_memfill(ary
, 0, capa
, Qnil
);
864 ARY_SET_LEN(ary
, capa
);
869 rb_ary_free(VALUE ary
)
871 if (ARY_OWNS_HEAP_P(ary
)) {
872 if (USE_DEBUG_COUNTER
&&
873 !ARY_SHARED_ROOT_P(ary
) &&
874 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
875 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
878 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
882 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
885 if (ARY_SHARED_P(ary
)) {
886 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
888 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
889 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
893 static VALUE fake_ary_flags
;
896 init_fake_ary_flags(void)
898 struct RArray fake_ary
= {0};
899 fake_ary
.basic
.flags
= T_ARRAY
;
900 VALUE ary
= (VALUE
)&fake_ary
;
902 return fake_ary
.basic
.flags
;
906 rb_setup_fake_ary(struct RArray
*fake_ary
, const VALUE
*list
, long len
)
908 fake_ary
->basic
.flags
= fake_ary_flags
;
909 RBASIC_CLEAR_CLASS((VALUE
)fake_ary
);
911 // bypass frozen checks
912 fake_ary
->as
.heap
.ptr
= list
;
913 fake_ary
->as
.heap
.len
= len
;
914 fake_ary
->as
.heap
.aux
.capa
= len
;
915 return (VALUE
)fake_ary
;
919 rb_ary_memsize(VALUE ary
)
921 if (ARY_OWNS_HEAP_P(ary
)) {
922 return ARY_CAPA(ary
) * sizeof(VALUE
);
930 ary_make_shared(VALUE ary
)
934 if (ARY_SHARED_P(ary
)) {
935 return ARY_SHARED_ROOT(ary
);
937 else if (ARY_SHARED_ROOT_P(ary
)) {
940 else if (OBJ_FROZEN(ary
)) {
944 long capa
= ARY_CAPA(ary
);
945 long len
= RARRAY_LEN(ary
);
947 /* Shared roots cannot be embedded because the reference count
948 * (refcnt) is stored in as.heap.aux.capa. */
949 VALUE shared
= ary_alloc_heap(0);
950 FL_SET_SHARED_ROOT(shared
);
952 if (ARY_EMBED_P(ary
)) {
953 VALUE
*ptr
= ary_heap_alloc_buffer(capa
);
954 ARY_SET_PTR(shared
, ptr
);
955 ary_memcpy(shared
, 0, len
, RARRAY_CONST_PTR(ary
));
958 ARY_SET_HEAP_LEN(ary
, len
);
959 ARY_SET_PTR(ary
, ptr
);
962 ARY_SET_PTR(shared
, RARRAY_CONST_PTR(ary
));
965 ARY_SET_LEN(shared
, capa
);
966 ary_mem_clear(shared
, len
, capa
- len
);
967 rb_ary_set_shared(ary
, shared
);
977 ary_make_substitution(VALUE ary
)
979 long len
= RARRAY_LEN(ary
);
981 if (ary_embeddable_p(len
)) {
982 VALUE subst
= rb_ary_new_capa(len
);
983 RUBY_ASSERT(ARY_EMBED_P(subst
));
985 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR(ary
));
986 ARY_SET_EMBED_LEN(subst
, len
);
990 return rb_ary_increment_share(ary_make_shared(ary
));
995 rb_assoc_new(VALUE car
, VALUE cdr
)
997 return rb_ary_new3(2, car
, cdr
);
1001 rb_to_array_type(VALUE ary
)
1003 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1005 #define to_ary rb_to_array_type
1008 rb_check_array_type(VALUE ary
)
1010 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1014 rb_check_to_array(VALUE ary
)
1016 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1020 rb_to_array(VALUE ary
)
1022 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1027 * Array.try_convert(object) -> object, new_array, or nil
1029 * Attempts to return an array, based on the given +object+.
1031 * If +object+ is an array, returns +object+.
1033 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1034 * calls <tt>object.to_ary</tt>:
1035 * if the return value is an array or +nil+, returns that value;
1036 * if not, raises TypeError.
1038 * Otherwise returns +nil+.
1040 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1044 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1046 return rb_check_array_type(ary
);
1051 rb_ary_s_new(int argc
, VALUE
*argv
, VALUE klass
)
1055 if (klass
== rb_cArray
) {
1057 if (argc
> 0 && FIXNUM_P(argv
[0])) {
1058 size
= FIX2LONG(argv
[0]);
1059 if (size
< 0) size
= 0;
1062 ary
= ary_new(klass
, size
);
1064 rb_obj_call_init_kw(ary
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
1067 ary
= rb_class_new_instance_pass_kw(argc
, argv
, klass
);
1075 * Array.new -> new_empty_array
1076 * Array.new(array) -> new_array
1077 * Array.new(size, default_value = nil) -> new_array
1078 * Array.new(size = 0) {|index| ... } -> new_array
1080 * Returns a new array.
1082 * With no block and no argument given, returns a new empty array:
1086 * With no block and array argument given, returns a new array with the same elements:
1088 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1090 * With no block and integer argument given, returns a new array containing
1091 * that many instances of the given +default_value+:
1093 * Array.new(0) # => []
1094 * Array.new(3) # => [nil, nil, nil]
1095 * Array.new(2, 3) # => [3, 3]
1097 * With a block given, returns an array of the given +size+;
1098 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1099 * the element at that +index+ in the returned array is the blocks return value:
1101 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1103 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1105 * array = Array.new(2, {})
1106 * array # => [{}, {}]
1108 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1110 * If you want the elements of the array to be distinct, you should pass a block:
1112 * array = Array.new(2) { {} }
1113 * array # => [{}, {}]
1115 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1117 * Raises TypeError if the first argument is not either an array
1118 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1119 * Raises ArgumentError if the first argument is a negative integer.
1121 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1125 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1133 RUBY_ASSERT(ARY_EMBED_P(ary
));
1134 RUBY_ASSERT(ARY_EMBED_LEN(ary
) == 0);
1135 if (rb_block_given_p()) {
1136 rb_warning("given block not used");
1140 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1141 if (argc
== 1 && !FIXNUM_P(size
)) {
1142 val
= rb_check_array_type(size
);
1144 rb_ary_replace(ary
, val
);
1149 len
= NUM2LONG(size
);
1150 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1152 rb_raise(rb_eArgError
, "negative array size");
1154 if (len
> ARY_MAX_SIZE
) {
1155 rb_raise(rb_eArgError
, "array size too big");
1157 /* recheck after argument conversion */
1159 ary_resize_capa(ary
, len
);
1160 if (rb_block_given_p()) {
1164 rb_warn("block supersedes default value argument");
1166 for (i
=0; i
<len
; i
++) {
1167 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1168 ARY_SET_LEN(ary
, i
+ 1);
1172 ary_memfill(ary
, 0, len
, val
);
1173 ARY_SET_LEN(ary
, len
);
1179 * Returns a new array, populated with the given objects:
1181 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1183 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1185 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1189 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1191 VALUE ary
= ary_new(klass
, argc
);
1192 if (argc
> 0 && argv
) {
1193 ary_memcpy(ary
, 0, argc
, argv
);
1194 ARY_SET_LEN(ary
, argc
);
1201 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1203 long len
= RARRAY_LEN(ary
);
1208 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1212 else if (idx
>= ARY_MAX_SIZE
) {
1213 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1217 if (idx
>= ARY_CAPA(ary
)) {
1218 ary_double_capa(ary
, idx
);
1221 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1225 ARY_SET_LEN(ary
, idx
+ 1);
1227 ARY_SET(ary
, idx
, val
);
1231 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1233 RUBY_ASSERT(offset
>= 0);
1234 RUBY_ASSERT(len
>= 0);
1235 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1237 VALUE result
= ary_alloc_heap(klass
);
1238 size_t embed_capa
= ary_embed_capa(result
);
1239 if ((size_t)len
<= embed_capa
) {
1240 FL_SET_EMBED(result
);
1241 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR(ary
) + offset
);
1242 ARY_SET_EMBED_LEN(result
, len
);
1245 VALUE shared
= ary_make_shared(ary
);
1247 /* The ary_make_shared call may allocate, which can trigger a GC
1248 * compaction. This can cause the array to be embedded because it has
1250 FL_UNSET_EMBED(result
);
1252 ARY_SET_PTR(result
, RARRAY_CONST_PTR(ary
));
1253 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1254 rb_ary_set_shared(result
, shared
);
1256 ARY_INCREASE_PTR(result
, offset
);
1257 ARY_SET_LEN(result
, len
);
1267 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1269 RUBY_ASSERT(offset
>= 0);
1270 RUBY_ASSERT(len
>= 0);
1271 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1272 RUBY_ASSERT(step
!= 0);
1274 const long orig_len
= len
;
1276 if (step
> 0 && step
>= len
) {
1277 VALUE result
= ary_new(klass
, 1);
1278 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1279 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1281 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1282 ARY_SET_EMBED_LEN(result
, 1);
1285 else if (step
< 0 && step
< -len
) {
1289 long ustep
= (step
< 0) ? -step
: step
;
1290 len
= roomof(len
, ustep
);
1293 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1295 VALUE result
= ary_new(klass
, len
);
1296 if (ARY_EMBED_P(result
)) {
1297 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1298 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1300 for (i
= 0; i
< len
; ++i
) {
1301 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1304 ARY_SET_EMBED_LEN(result
, len
);
1307 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1309 RARRAY_PTR_USE(result
, ptr
, {
1310 for (i
= 0; i
< len
; ++i
) {
1311 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1315 ARY_SET_LEN(result
, len
);
1322 ary_make_shared_copy(VALUE ary
)
1324 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1327 enum ary_take_pos_flags
1334 ary_take_first_or_last_n(VALUE ary
, long n
, enum ary_take_pos_flags last
)
1336 long len
= RARRAY_LEN(ary
);
1343 rb_raise(rb_eArgError
, "negative array size");
1348 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1352 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1354 argc
= rb_check_arity(argc
, 0, 1);
1355 /* the case optional argument is omitted should be handled in
1356 * callers of this function. if another arity case is added,
1357 * this arity check needs to rewrite. */
1358 RUBY_ASSERT_ALWAYS(argc
== 1);
1359 return ary_take_first_or_last_n(ary
, NUM2LONG(argv
[0]), last
);
1364 * self << object -> self
1366 * Appends +object+ as the last element in +self+; returns +self+:
1368 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1370 * Appends +object+ as a single element, even if it is another array:
1372 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1374 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1378 rb_ary_push(VALUE ary
, VALUE item
)
1380 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1381 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1382 RARRAY_PTR_USE(ary
, ptr
, {
1383 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1385 ARY_SET_LEN(ary
, idx
+ 1);
1391 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1393 long oldlen
= RARRAY_LEN(ary
);
1394 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1395 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1396 ARY_SET_LEN(ary
, oldlen
+ len
);
1402 * push(*objects) -> self
1403 * append(*objects) -> self
1405 * Appends each argument in +objects+ to +self+; returns +self+:
1407 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1408 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1410 * Appends each argument as a single element, even if it is another array:
1412 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1413 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1415 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1419 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1421 return rb_ary_cat(ary
, argv
, argc
);
1425 rb_ary_pop(VALUE ary
)
1428 rb_ary_modify_check(ary
);
1429 n
= RARRAY_LEN(ary
);
1430 if (n
== 0) return Qnil
;
1431 if (ARY_OWNS_HEAP_P(ary
) &&
1432 n
* 3 < ARY_CAPA(ary
) &&
1433 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1435 ary_resize_capa(ary
, n
* 2);
1438 ARY_SET_LEN(ary
, n
);
1440 return RARRAY_AREF(ary
, n
);
1445 * pop -> object or nil
1446 * pop(count) -> new_array
1448 * Removes and returns trailing elements of +self+.
1450 * With no argument given, removes and returns the last element, if available;
1451 * otherwise returns +nil+:
1453 * a = [:foo, 'bar', 2]
1455 * a # => [:foo, "bar"]
1458 * With non-negative integer argument +count+ given,
1459 * returns a new array containing the trailing +count+ elements of +self+, as available:
1461 * a = [:foo, 'bar', 2]
1462 * a.pop(2) # => ["bar", 2]
1465 * a = [:foo, 'bar', 2]
1466 * a.pop(50) # => [:foo, "bar", 2]
1469 * Related: Array#push;
1470 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1474 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1479 return rb_ary_pop(ary
);
1482 rb_ary_modify_check(ary
);
1483 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1484 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1490 rb_ary_shift(VALUE ary
)
1493 long len
= RARRAY_LEN(ary
);
1496 rb_ary_modify_check(ary
);
1500 top
= RARRAY_AREF(ary
, 0);
1502 rb_ary_behead(ary
, 1);
1509 * shift -> object or nil
1510 * shift(count) -> new_array or nil
1512 * Removes and returns leading elements from +self+.
1514 * With no argument, removes and returns one element, if available,
1515 * or +nil+ otherwise:
1522 * With non-negative numeric argument +count+ given,
1523 * removes and returns the first +count+ elements:
1526 * a.shift(2) # => [0, 1]
1528 * a.shift(1.1) # => [2]
1530 * a.shift(0) # => []
1533 * If +count+ is large,
1534 * removes and returns all elements:
1537 * a.shift(50) # => [0, 1, 2, 3]
1540 * If +self+ is empty, returns a new empty array.
1542 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1546 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1552 return rb_ary_shift(ary
);
1555 rb_ary_modify_check(ary
);
1556 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1557 n
= RARRAY_LEN(result
);
1558 rb_ary_behead(ary
,n
);
1564 rb_ary_behead(VALUE ary
, long n
)
1570 rb_ary_modify_check(ary
);
1572 if (!ARY_SHARED_P(ary
)) {
1573 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1574 RARRAY_PTR_USE(ary
, ptr
, {
1575 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1576 }); /* WB: no new reference */
1577 ARY_INCREASE_LEN(ary
, -n
);
1582 ary_mem_clear(ary
, 0, n
);
1583 ary_make_shared(ary
);
1585 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1586 ary_mem_clear(ary
, 0, n
);
1589 ARY_INCREASE_PTR(ary
, n
);
1590 ARY_INCREASE_LEN(ary
, -n
);
1597 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1599 if (head
- sharedp
< argc
) {
1600 long room
= capa
- len
- argc
;
1603 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1604 head
= sharedp
+ argc
+ room
;
1606 ARY_SET_PTR(ary
, head
- argc
);
1607 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1610 return ARY_SHARED_ROOT(ary
);
1614 ary_modify_for_unshift(VALUE ary
, int argc
)
1616 long len
= RARRAY_LEN(ary
);
1617 long new_len
= len
+ argc
;
1619 const VALUE
*head
, *sharedp
;
1622 capa
= ARY_CAPA(ary
);
1623 if (capa
- (capa
>> 6) <= new_len
) {
1624 ary_double_capa(ary
, new_len
);
1627 /* use shared array for big "queues" */
1628 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1631 /* make a room for unshifted items */
1632 capa
= ARY_CAPA(ary
);
1633 ary_make_shared(ary
);
1635 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1636 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1640 RARRAY_PTR_USE(ary
, ptr
, {
1641 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1650 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1652 long len
= RARRAY_LEN(ary
);
1653 long new_len
= len
+ argc
;
1655 if (len
> ARY_MAX_SIZE
- argc
) {
1656 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1658 else if (! ARY_SHARED_P(ary
)) {
1659 return ary_modify_for_unshift(ary
, argc
);
1662 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1663 long capa
= RARRAY_LEN(shared_root
);
1665 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1666 return ary_modify_for_unshift(ary
, argc
);
1668 else if (new_len
> capa
) {
1669 return ary_modify_for_unshift(ary
, argc
);
1672 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1673 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1675 rb_ary_modify_check(ary
);
1676 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1683 * unshift(*objects) -> self
1684 * prepend(*objects) -> self
1686 * Prepends the given +objects+ to +self+:
1688 * a = [:foo, 'bar', 2]
1689 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1691 * Related: Array#shift;
1692 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1696 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1698 long len
= RARRAY_LEN(ary
);
1702 rb_ary_modify_check(ary
);
1706 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1707 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1708 ARY_SET_LEN(ary
, len
+ argc
);
1713 rb_ary_unshift(VALUE ary
, VALUE item
)
1715 return rb_ary_unshift_m(1, &item
, ary
);
1718 /* faster version - use this if you don't need to treat negative offset */
1720 rb_ary_elt(VALUE ary
, long offset
)
1722 long len
= RARRAY_LEN(ary
);
1723 if (len
== 0) return Qnil
;
1724 if (offset
< 0 || len
<= offset
) {
1727 return RARRAY_AREF(ary
, offset
);
1731 rb_ary_entry(VALUE ary
, long offset
)
1733 return rb_ary_entry_internal(ary
, offset
);
1737 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1740 long alen
= RARRAY_LEN(ary
);
1742 if (beg
> alen
) return Qnil
;
1743 if (beg
< 0 || len
< 0) return Qnil
;
1745 if (alen
< len
|| alen
< beg
+ len
) {
1749 if (len
== 0) return ary_new(klass
, 0);
1751 rb_raise(rb_eArgError
, "slice step cannot be zero");
1753 return ary_make_partial(ary
, klass
, beg
, len
);
1755 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1759 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1761 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1764 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1768 * self[index] -> object or nil
1769 * self[start, length] -> object or nil
1770 * self[range] -> object or nil
1771 * self[aseq] -> object or nil
1772 * slice(index) -> object or nil
1773 * slice(start, length) -> object or nil
1774 * slice(range) -> object or nil
1775 * slice(aseq) -> object or nil
1777 * Returns elements from +self+; does not modify +self+.
1781 * a = [:foo, 'bar', 2]
1783 * # Single argument index: returns one element.
1784 * a[0] # => :foo # Zero-based index.
1785 * a[-1] # => 2 # Negative index counts backwards from end.
1787 * # Arguments start and length: returns an array.
1788 * a[1, 2] # => ["bar", 2]
1789 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1791 * # Single argument range: returns an array.
1792 * a[0..1] # => [:foo, "bar"]
1793 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1794 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1796 * When a single integer argument +index+ is given, returns the element at offset +index+:
1798 * a = [:foo, 'bar', 2]
1801 * a # => [:foo, "bar", 2]
1803 * If +index+ is negative, counts backwards from the end of +self+:
1805 * a = [:foo, 'bar', 2]
1809 * If +index+ is out of range, returns +nil+.
1811 * When two Integer arguments +start+ and +length+ are given,
1812 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1814 * a = [:foo, 'bar', 2]
1815 * a[0, 2] # => [:foo, "bar"]
1816 * a[1, 2] # => ["bar", 2]
1818 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1819 * returns all elements from offset +start+ to the end:
1821 * a = [:foo, 'bar', 2]
1822 * a[0, 4] # => [:foo, "bar", 2]
1823 * a[1, 3] # => ["bar", 2]
1826 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1827 * returns a new empty +Array+.
1829 * If +length+ is negative, returns +nil+.
1831 * When a single Range argument +range+ is given,
1832 * treats <tt>range.min</tt> as +start+ above
1833 * and <tt>range.size</tt> as +length+ above:
1835 * a = [:foo, 'bar', 2]
1836 * a[0..1] # => [:foo, "bar"]
1837 * a[1..2] # => ["bar", 2]
1839 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1841 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1843 * a = [:foo, 'bar', 2]
1844 * a[0..-1] # => [:foo, "bar", 2]
1845 * a[0..-2] # => [:foo, "bar"]
1846 * a[0..-3] # => [:foo]
1848 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1850 * a = [:foo, 'bar', 2]
1852 * a[-2..2] # => ["bar", 2]
1853 * a[-3..2] # => [:foo, "bar", 2]
1855 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1857 * a = [:foo, 'bar', 2]
1862 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1863 * returns an +Array+ of elements corresponding to the indexes produced by
1866 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1867 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1869 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1870 * is larger than array size, throws RangeError.
1872 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1873 * a[(1..11).step(2)]
1874 * # RangeError (((1..11).step(2)) out of range)
1876 * # RangeError (((7..).step(2)) out of range)
1878 * If given a single argument, and its type is not one of the listed, tries to
1879 * convert it to Integer, and raises if it is impossible:
1881 * a = [:foo, 'bar', 2]
1882 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1885 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1889 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1891 rb_check_arity(argc
, 1, 2);
1893 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1895 return rb_ary_aref1(ary
, argv
[0]);
1899 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1901 long beg
= NUM2LONG(b
);
1902 long len
= NUM2LONG(e
);
1904 beg
+= RARRAY_LEN(ary
);
1906 return rb_ary_subseq(ary
, beg
, len
);
1910 rb_ary_aref1(VALUE ary
, VALUE arg
)
1912 long beg
, len
, step
;
1914 /* special case - speeding up */
1915 if (FIXNUM_P(arg
)) {
1916 return rb_ary_entry(ary
, FIX2LONG(arg
));
1918 /* check if idx is Range or ArithmeticSequence */
1919 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1925 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1928 return rb_ary_entry(ary
, NUM2LONG(arg
));
1933 * at(index) -> object or nil
1935 * Returns the element of +self+ specified by the given +index+
1936 * or +nil+ if there is no such element;
1937 * +index+ must be an
1938 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1940 * For non-negative +index+, returns the element of +self+ at offset +index+:
1942 * a = [:foo, 'bar', 2]
1947 * For negative +index+, counts backwards from the end of +self+:
1949 * a.at(-2) # => "bar"
1951 * Related: Array#[];
1952 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1956 rb_ary_at(VALUE ary
, VALUE pos
)
1958 return rb_ary_entry(ary
, NUM2LONG(pos
));
1963 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1966 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1967 return RARRAY_AREF(ary
, 0);
1970 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1976 ary_first(VALUE self
)
1978 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1982 ary_last(VALUE self
)
1984 long len
= RARRAY_LEN(self
);
1985 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1989 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1992 return ary_last(ary
);
1995 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
2001 * fetch(index) -> element
2002 * fetch(index, default_value) -> element or default_value
2003 * fetch(index) {|index| ... } -> element or block_return_value
2005 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2006 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2008 * With the single argument +index+ and no block,
2009 * returns the element at offset +index+:
2011 * a = [:foo, 'bar', 2]
2012 * a.fetch(1) # => "bar"
2013 * a.fetch(1.1) # => "bar"
2015 * If +index+ is negative, counts from the end of the array:
2017 * a = [:foo, 'bar', 2]
2018 * a.fetch(-1) # => 2
2019 * a.fetch(-2) # => "bar"
2021 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2022 * returns +default_value+ if +index+ is out-of-range:
2024 * a = [:foo, 'bar', 2]
2025 * a.fetch(1, nil) # => "bar"
2026 * a.fetch(3, :foo) # => :foo
2028 * With argument +index+ and a block,
2029 * returns the element at offset +index+ if index is in range
2030 * (and the block is not called); otherwise calls the block with index and returns its return value:
2032 * a = [:foo, 'bar', 2]
2033 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2034 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2036 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2040 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
2046 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
2047 block_given
= rb_block_given_p();
2048 if (block_given
&& argc
== 2) {
2049 rb_warn("block supersedes default value argument");
2051 idx
= NUM2LONG(pos
);
2054 idx
+= RARRAY_LEN(ary
);
2056 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2057 if (block_given
) return rb_yield(pos
);
2059 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2060 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2064 return RARRAY_AREF(ary
, idx
);
2069 * find_index(object) -> integer or nil
2070 * find_index {|element| ... } -> integer or nil
2071 * find_index -> new_enumerator
2072 * index(object) -> integer or nil
2073 * index {|element| ... } -> integer or nil
2074 * index -> new_enumerator
2076 * Returns the zero-based integer index of a specified element, or +nil+.
2078 * With only argument +object+ given,
2079 * returns the index of the first element +element+
2080 * for which <tt>object == element</tt>:
2082 * a = [:foo, 'bar', 2, 'bar']
2083 * a.index('bar') # => 1
2085 * Returns +nil+ if no such element found.
2087 * With only a block given,
2088 * calls the block with each successive element;
2089 * returns the index of the first element for which the block returns a truthy value:
2091 * a = [:foo, 'bar', 2, 'bar']
2092 * a.index {|element| element == 'bar' } # => 1
2094 * Returns +nil+ if the block never returns a truthy value.
2096 * With neither an argument nor a block given, returns a new Enumerator.
2098 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2102 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2108 RETURN_ENUMERATOR(ary
, 0, 0);
2109 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2110 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2116 rb_check_arity(argc
, 0, 1);
2118 if (rb_block_given_p())
2119 rb_warn("given block not used");
2120 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2121 VALUE e
= RARRAY_AREF(ary
, i
);
2122 if (rb_equal(e
, val
)) {
2131 * rindex(object) -> integer or nil
2132 * rindex {|element| ... } -> integer or nil
2133 * rindex -> new_enumerator
2135 * Returns the index of the last element for which <tt>object == element</tt>.
2137 * With argument +object+ given, returns the index of the last such element found:
2139 * a = [:foo, 'bar', 2, 'bar']
2140 * a.rindex('bar') # => 3
2142 * Returns +nil+ if no such object found.
2144 * With a block given, calls the block with each successive element;
2145 * returns the index of the last element for which the block returns a truthy value:
2147 * a = [:foo, 'bar', 2, 'bar']
2148 * a.rindex {|element| element == 'bar' } # => 3
2150 * Returns +nil+ if the block never returns a truthy value.
2152 * When neither an argument nor a block is given, returns a new Enumerator.
2154 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2158 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2161 long i
= RARRAY_LEN(ary
), len
;
2164 RETURN_ENUMERATOR(ary
, 0, 0);
2166 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2168 if (i
> (len
= RARRAY_LEN(ary
))) {
2174 rb_check_arity(argc
, 0, 1);
2176 if (rb_block_given_p())
2177 rb_warn("given block not used");
2179 VALUE e
= RARRAY_AREF(ary
, i
);
2180 if (rb_equal(e
, val
)) {
2183 if (i
> RARRAY_LEN(ary
)) {
2191 rb_ary_to_ary(VALUE obj
)
2193 VALUE tmp
= rb_check_array_type(obj
);
2195 if (!NIL_P(tmp
)) return tmp
;
2196 return rb_ary_new3(1, obj
);
2200 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2205 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2206 olen
= RARRAY_LEN(ary
);
2210 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2214 if (olen
< len
|| olen
< beg
+ len
) {
2219 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2220 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2225 if (beg
> ARY_MAX_SIZE
- rlen
) {
2226 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2228 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2230 ary_mem_clear(ary
, olen
, beg
- olen
);
2232 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2233 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2235 ARY_SET_LEN(ary
, len
);
2240 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2241 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2244 alen
= olen
+ rlen
- len
;
2245 if (alen
>= ARY_CAPA(ary
)) {
2246 ary_double_capa(ary
, alen
);
2250 RARRAY_PTR_USE(ary
, ptr
,
2251 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2252 VALUE
, olen
- (beg
+ len
)));
2253 ARY_SET_LEN(ary
, alen
);
2257 rb_gc_writebarrier_remember(ary
);
2260 /* In this case, we're copying from a region in this array, so
2261 * we don't need to fire the write barrier. */
2262 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2265 /* do not use RARRAY_PTR() because it can causes GC.
2266 * ary can contain T_NONE object because it is not cleared.
2268 RARRAY_PTR_USE(ary
, ptr
,
2269 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2275 rb_ary_set_len(VALUE ary
, long len
)
2279 rb_ary_modify_check(ary
);
2280 if (ARY_SHARED_P(ary
)) {
2281 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2283 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2284 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2286 ARY_SET_LEN(ary
, len
);
2290 rb_ary_resize(VALUE ary
, long len
)
2295 olen
= RARRAY_LEN(ary
);
2296 if (len
== olen
) return ary
;
2297 if (len
> ARY_MAX_SIZE
) {
2298 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2301 if (len
> ARY_CAPA(ary
)) {
2302 ary_double_capa(ary
, len
);
2304 ary_mem_clear(ary
, olen
, len
- olen
);
2305 ARY_SET_LEN(ary
, len
);
2307 else if (ARY_EMBED_P(ary
)) {
2308 ARY_SET_EMBED_LEN(ary
, len
);
2310 else if (len
<= ary_embed_capa(ary
)) {
2311 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2312 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2313 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2317 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2318 ARY_SET_EMBED_LEN(ary
, len
);
2320 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2323 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2324 size_t new_capa
= ary_heap_realloc(ary
, len
);
2325 ARY_SET_CAPA(ary
, new_capa
);
2327 ARY_SET_HEAP_LEN(ary
, len
);
2334 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2336 rb_ary_store(ary
, key
, val
);
2341 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2343 VALUE rpl
= rb_ary_to_ary(val
);
2344 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2351 * self[index] = object -> object
2352 * self[start, length] = object -> object
2353 * self[range] = object -> object
2355 * Assigns elements in +self+, based on the given +object+; returns +object+.
2359 * a_orig = [:foo, 'bar', 2]
2361 * # With argument index.
2363 * a[0] = 'foo' # => "foo"
2364 * a # => ["foo", "bar", 2]
2366 * a[7] = 'foo' # => "foo"
2367 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2369 * # With arguments start and length.
2371 * a[0, 2] = 'foo' # => "foo"
2374 * a[6, 50] = 'foo' # => "foo"
2375 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2377 * # With argument range.
2379 * a[0..1] = 'foo' # => "foo"
2382 * a[6..50] = 'foo' # => "foo"
2383 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2385 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2387 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2389 * a = [:foo, 'bar', 2]
2390 * a[0] = 'foo' # => "foo"
2391 * a # => ["foo", "bar", 2]
2393 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2395 * a = [:foo, 'bar', 2]
2396 * a[7] = 'foo' # => "foo"
2397 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2399 * If +index+ is negative, counts backwards from the end of the array:
2401 * a = [:foo, 'bar', 2]
2402 * a[-1] = 'two' # => "two"
2403 * a # => [:foo, "bar", "two"]
2405 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2406 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2407 * and assigns +object+ at offset +start+:
2409 * a = [:foo, 'bar', 2]
2410 * a[0, 2] = 'foo' # => "foo"
2413 * If +start+ is negative, counts backwards from the end of the array:
2415 * a = [:foo, 'bar', 2]
2416 * a[-2, 2] = 'foo' # => "foo"
2417 * a # => [:foo, "foo"]
2419 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2420 * extends the array with +nil+, assigns +object+ at offset +start+,
2421 * and ignores +length+:
2423 * a = [:foo, 'bar', 2]
2424 * a[6, 50] = 'foo' # => "foo"
2425 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2427 * If +length+ is zero, shifts elements at and following offset +start+
2428 * and assigns +object+ at offset +start+:
2430 * a = [:foo, 'bar', 2]
2431 * a[1, 0] = 'foo' # => "foo"
2432 * a # => [:foo, "foo", "bar", 2]
2434 * If +length+ is too large for the existing array, does not extend the array:
2436 * a = [:foo, 'bar', 2]
2437 * a[1, 5] = 'foo' # => "foo"
2438 * a # => [:foo, "foo"]
2440 * When Range argument +range+ is given and +object+ is not an +Array+,
2441 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2442 * and assigns +object+ at offset +start+:
2444 * a = [:foo, 'bar', 2]
2445 * a[0..1] = 'foo' # => "foo"
2448 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2450 * a = [:foo, 'bar', 2]
2451 * a[-2..2] = 'foo' # => "foo"
2452 * a # => [:foo, "foo"]
2454 * If the array length is less than <tt>range.begin</tt>,
2455 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2456 * and ignores +length+:
2458 * a = [:foo, 'bar', 2]
2459 * a[6..50] = 'foo' # => "foo"
2460 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2462 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2463 * and assigns +object+ at offset +start+:
2465 * a = [:foo, 'bar', 2]
2466 * a[1..0] = 'foo' # => "foo"
2467 * a # => [:foo, "foo", "bar", 2]
2469 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2470 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2472 * a = [:foo, 'bar', 2]
2473 * a[1..-1] = 'foo' # => "foo"
2474 * a # => [:foo, "foo"]
2475 * a = [:foo, 'bar', 2]
2476 * a[1..-2] = 'foo' # => "foo"
2477 * a # => [:foo, "foo", 2]
2478 * a = [:foo, 'bar', 2]
2479 * a[1..-3] = 'foo' # => "foo"
2480 * a # => [:foo, "foo", "bar", 2]
2481 * a = [:foo, 'bar', 2]
2483 * If <tt>range.end</tt> is too large for the existing array,
2484 * replaces array elements, but does not extend the array with +nil+ values:
2486 * a = [:foo, 'bar', 2]
2487 * a[1..5] = 'foo' # => "foo"
2488 * a # => [:foo, "foo"]
2490 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2494 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2496 long offset
, beg
, len
;
2498 rb_check_arity(argc
, 2, 3);
2499 rb_ary_modify_check(ary
);
2501 beg
= NUM2LONG(argv
[0]);
2502 len
= NUM2LONG(argv
[1]);
2503 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2505 if (FIXNUM_P(argv
[0])) {
2506 offset
= FIX2LONG(argv
[0]);
2507 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2509 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2510 /* check if idx is Range */
2511 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2514 offset
= NUM2LONG(argv
[0]);
2515 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2520 * insert(index, *objects) -> self
2522 * Inserts the given +objects+ as elements of +self+;
2525 * When +index+ is non-negative, inserts +objects+
2526 * _before_ the element at offset +index+:
2528 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2529 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2531 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2533 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2534 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2536 * When +index+ is negative, inserts +objects+
2537 * _after_ the element at offset <tt>index + self.size</tt>:
2539 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2540 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2542 * With no +objects+ given, does nothing:
2544 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2545 * a.insert(1) # => ["a", "b", "c"]
2546 * a.insert(50) # => ["a", "b", "c"]
2547 * a.insert(-50) # => ["a", "b", "c"]
2549 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2551 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2555 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2559 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2560 rb_ary_modify_check(ary
);
2561 pos
= NUM2LONG(argv
[0]);
2562 if (argc
== 1) return ary
;
2564 pos
= RARRAY_LEN(ary
);
2567 long minpos
= -RARRAY_LEN(ary
) - 1;
2569 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2574 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2579 rb_ary_length(VALUE ary
);
2582 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2584 return rb_ary_length(ary
);
2587 // Primitive to avoid a race condition in Array#each.
2588 // Return `true` and write `value` and `index` if the element exists.
2590 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2592 long i
= NUM2LONG(*index
);
2593 if (i
>= RARRAY_LEN(self
)) {
2596 *value
= RARRAY_AREF(self
, i
);
2597 *index
= LONG2NUM(i
+ 1);
2603 * each {|element| ... } -> self
2604 * each -> new_enumerator
2606 * With a block given, iterates over the elements of +self+,
2607 * passing each element to the block;
2610 * a = [:foo, 'bar', 2]
2611 * a.each {|element| puts "#{element.class} #{element}" }
2619 * Allows the array to be modified during iteration:
2621 * a = [:foo, 'bar', 2]
2622 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2629 * With no block given, returns a new Enumerator.
2631 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2635 rb_ary_each(VALUE ary
)
2639 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2640 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2641 rb_yield(RARRAY_AREF(ary
, i
));
2648 * each_index {|index| ... } -> self
2649 * each_index -> new_enumerator
2651 * With a block given, iterates over the elements of +self+,
2652 * passing each <i>array index</i> to the block;
2655 * a = [:foo, 'bar', 2]
2656 * a.each_index {|index| puts "#{index} #{a[index]}" }
2664 * Allows the array to be modified during iteration:
2666 * a = [:foo, 'bar', 2]
2667 * a.each_index {|index| puts index; a.clear if index > 0 }
2675 * With no block given, returns a new Enumerator.
2677 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2681 rb_ary_each_index(VALUE ary
)
2684 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2686 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2687 rb_yield(LONG2NUM(i
));
2694 * reverse_each {|element| ... } -> self
2695 * reverse_each -> Enumerator
2697 * When a block given, iterates backwards over the elements of +self+,
2698 * passing, in reverse order, each element to the block;
2702 * [0, 1, 2].reverse_each {|element| a.push(element) }
2705 * Allows the array to be modified during iteration:
2707 * a = ['a', 'b', 'c']
2708 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2711 * When no block given, returns a new Enumerator.
2713 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2717 rb_ary_reverse_each(VALUE ary
)
2721 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2722 len
= RARRAY_LEN(ary
);
2725 rb_yield(RARRAY_AREF(ary
, len
));
2726 nlen
= RARRAY_LEN(ary
);
2739 * Returns the count of elements in +self+:
2741 * [0, 1, 2].length # => 3
2744 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2748 rb_ary_length(VALUE ary
)
2750 long len
= RARRAY_LEN(ary
);
2751 return LONG2NUM(len
);
2756 * array.empty? -> true or false
2758 * Returns +true+ if the count of elements in +self+ is zero,
2759 * +false+ otherwise.
2761 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2765 rb_ary_empty_p(VALUE ary
)
2767 return RBOOL(RARRAY_LEN(ary
) == 0);
2771 rb_ary_dup(VALUE ary
)
2773 long len
= RARRAY_LEN(ary
);
2774 VALUE dup
= rb_ary_new2(len
);
2775 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2776 ARY_SET_LEN(dup
, len
);
2784 rb_ary_resurrect(VALUE ary
)
2786 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2789 extern VALUE rb_output_fs
;
2791 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2794 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2796 VALUE
*arg
= (VALUE
*)argp
;
2799 VALUE result
= arg
[2];
2800 int *first
= (int *)arg
[3];
2803 rb_raise(rb_eArgError
, "recursive array join");
2806 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2812 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2817 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2818 for (i
=0; i
<max
; i
++) {
2819 val
= RARRAY_AREF(ary
, i
);
2820 if (!RB_TYPE_P(val
, T_STRING
)) break;
2821 if (i
> 0 && !NIL_P(sep
))
2822 rb_str_buf_append(result
, sep
);
2823 rb_str_buf_append(result
, val
);
2829 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2831 rb_str_buf_append(dst
, src
);
2833 rb_enc_copy(dst
, src
);
2839 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2842 rb_raise(rb_eArgError
, "recursive array join");
2851 args
[3] = (VALUE
)first
;
2852 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2857 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2861 for (; i
<RARRAY_LEN(ary
); i
++) {
2862 if (i
> 0 && !NIL_P(sep
))
2863 rb_str_buf_append(result
, sep
);
2865 val
= RARRAY_AREF(ary
, i
);
2866 if (RB_TYPE_P(val
, T_STRING
)) {
2867 ary_join_1_str(result
, val
, first
);
2869 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2870 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2872 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2873 ary_join_1_str(result
, tmp
, first
);
2875 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2876 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2879 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2885 rb_ary_join(VALUE ary
, VALUE sep
)
2888 VALUE val
, tmp
, result
;
2890 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2894 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2896 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2897 val
= RARRAY_AREF(ary
, i
);
2898 tmp
= rb_check_string_type(val
);
2900 if (NIL_P(tmp
) || tmp
!= val
) {
2902 long n
= RARRAY_LEN(ary
);
2904 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2905 rb_enc_associate(result
, rb_usascii_encoding());
2906 i
= ary_join_0(ary
, sep
, i
, result
);
2908 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2912 len
+= RSTRING_LEN(tmp
);
2915 result
= rb_str_new(0, len
);
2916 rb_str_set_len(result
, 0);
2918 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2925 * array.join(separator = $,) -> new_string
2927 * Returns the new string formed by joining the converted elements of +self+;
2928 * for each element +element+:
2930 * - Converts recursively using <tt>element.join(separator)</tt>
2931 * if +element+ is a <tt>kind_of?(Array)</tt>.
2932 * - Otherwise, converts using <tt>element.to_s</tt>.
2934 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2936 * a = [:foo, 'bar', 2]
2938 * a.join # => "foobar2"
2940 * With string argument +separator+ given, joins using that separator:
2942 * a = [:foo, 'bar', 2]
2943 * a.join("\n") # => "foo\nbar\n2"
2945 * Joins recursively for nested arrays:
2947 * a = [:foo, [:bar, [:baz, :bat]]]
2948 * a.join # => "foobarbazbat"
2950 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2953 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2957 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2960 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2964 return rb_ary_join(ary
, sep
);
2968 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2973 if (recur
) return rb_usascii_str_new_cstr("[...]");
2974 str
= rb_str_buf_new2("[");
2975 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2976 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2977 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2978 else rb_enc_copy(str
, s
);
2979 rb_str_buf_append(str
, s
);
2981 rb_str_buf_cat2(str
, "]");
2987 * inspect -> new_string
2988 * to_s -> new_string
2990 * Returns the new string formed by calling method <tt>#inspect</tt>
2991 * on each array element:
2993 * a = [:foo, 'bar', 2]
2994 * a.inspect # => "[:foo, \"bar\", 2]"
2996 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3000 rb_ary_inspect(VALUE ary
)
3002 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
3003 return rb_exec_recursive(inspect_ary
, ary
, 0);
3007 rb_ary_to_s(VALUE ary
)
3009 return rb_ary_inspect(ary
);
3014 * to_a -> self or new_array
3016 * When +self+ is an instance of +Array+, returns +self+.
3018 * Otherwise, returns a new array containing the elements of +self+:
3020 * class MyArray < Array; end
3021 * my_a = MyArray.new(['foo', 'bar', 'two'])
3023 * a # => ["foo", "bar", "two"]
3024 * a.class # => Array # Not MyArray.
3026 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3030 rb_ary_to_a(VALUE ary
)
3032 if (rb_obj_class(ary
) != rb_cArray
) {
3033 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
3034 rb_ary_replace(dup
, ary
);
3043 * to_h {|element| ... } -> new_hash
3045 * Returns a new hash formed from +self+.
3047 * With no block given, each element of +self+ must be a 2-element sub-array;
3048 * forms each sub-array into a key-value pair in the new hash:
3050 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3051 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3054 * With a block given, the block must return a 2-element array;
3055 * calls the block with each element of +self+;
3056 * forms each returned array into a key-value pair in the returned hash:
3058 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3059 * a.to_h {|element| [element, element.class] }
3060 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3062 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3066 rb_ary_to_h(VALUE ary
)
3069 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
3070 int block_given
= rb_block_given_p();
3072 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3073 const VALUE e
= rb_ary_elt(ary
, i
);
3074 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3075 const VALUE key_value_pair
= rb_check_array_type(elt
);
3076 if (NIL_P(key_value_pair
)) {
3077 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3078 rb_obj_class(elt
), i
);
3080 if (RARRAY_LEN(key_value_pair
) != 2) {
3081 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3082 i
, RARRAY_LEN(key_value_pair
));
3084 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3091 * array.to_ary -> self
3097 rb_ary_to_ary_m(VALUE ary
)
3103 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3113 rb_ary_reverse(VALUE ary
)
3116 long len
= RARRAY_LEN(ary
);
3120 RARRAY_PTR_USE(ary
, p1
, {
3121 p2
= p1
+ len
- 1; /* points last item */
3122 ary_reverse(p1
, p2
);
3123 }); /* WB: no new reference */
3132 * Reverses the order of the elements of +self+;
3136 * a.reverse! # => [2, 1, 0]
3139 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3143 rb_ary_reverse_bang(VALUE ary
)
3145 return rb_ary_reverse(ary
);
3150 * reverse -> new_array
3152 * Returns a new array containing the elements of +self+ in reverse order:
3154 * [0, 1, 2].reverse # => [2, 1, 0]
3156 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3160 rb_ary_reverse_m(VALUE ary
)
3162 long len
= RARRAY_LEN(ary
);
3163 VALUE dup
= rb_ary_new2(len
);
3166 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3167 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3168 do *p2
-- = *p1
++; while (--len
> 0);
3170 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3175 rotate_count(long cnt
, long len
)
3177 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3181 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3185 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3186 *(ptr
+ len
- 1) = tmp
;
3188 else if (cnt
== len
- 1) {
3189 VALUE tmp
= *(ptr
+ len
- 1);
3190 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3195 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3196 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3197 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3202 rb_ary_rotate(VALUE ary
, long cnt
)
3207 long len
= RARRAY_LEN(ary
);
3208 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3209 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3218 * rotate!(count = 1) -> self
3220 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3222 * With non-negative numeric +count+,
3223 * rotates +count+ elements from the beginning to the end:
3225 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3226 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3228 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3230 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3232 * If +count+ is zero, rotates no elements:
3234 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3236 * With a negative numeric +count+, rotates in the opposite direction,
3237 * from end to beginning:
3239 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3241 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3243 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3245 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3249 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3251 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3252 rb_ary_rotate(ary
, n
);
3258 * rotate(count = 1) -> new_array
3260 * Returns a new array formed from +self+ with elements
3261 * rotated from one end to the other.
3263 * With non-negative numeric +count+,
3264 * rotates elements from the beginning to the end:
3266 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3267 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3269 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3271 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3273 * With a +count+ of zero, rotates no elements:
3275 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3277 * With negative numeric +count+, rotates in the opposite direction,
3278 * from the end to the beginning:
3280 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3282 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3284 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3286 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3290 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3295 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3297 len
= RARRAY_LEN(ary
);
3298 rotated
= rb_ary_new2(len
);
3300 cnt
= rotate_count(cnt
, len
);
3301 ptr
= RARRAY_CONST_PTR(ary
);
3303 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3304 ary_memcpy(rotated
, len
, cnt
, ptr
);
3306 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3310 struct ary_sort_data
{
3316 sort_reentered(VALUE ary
)
3318 if (RBASIC(ary
)->klass
) {
3319 rb_raise(rb_eRuntimeError
, "sort reentered");
3325 sort_returned(struct ary_sort_data
*data
)
3327 if (rb_obj_frozen_p(data
->receiver
)) {
3328 rb_raise(rb_eFrozenError
, "array frozen during sort");
3330 sort_reentered(data
->ary
);
3334 sort_1(const void *ap
, const void *bp
, void *dummy
)
3336 struct ary_sort_data
*data
= dummy
;
3337 VALUE retval
= sort_reentered(data
->ary
);
3338 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3344 retval
= rb_yield_values2(2, args
);
3345 n
= rb_cmpint(retval
, a
, b
);
3346 sort_returned(data
);
3351 sort_2(const void *ap
, const void *bp
, void *dummy
)
3353 struct ary_sort_data
*data
= dummy
;
3354 VALUE retval
= sort_reentered(data
->ary
);
3355 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3358 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3359 if ((long)a
> (long)b
) return 1;
3360 if ((long)a
< (long)b
) return -1;
3363 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3364 return rb_str_cmp(a
, b
);
3366 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3367 return rb_float_cmp(a
, b
);
3370 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3371 n
= rb_cmpint(retval
, a
, b
);
3372 sort_returned(data
);
3380 * sort! {|a, b| ... } -> self
3382 * Like Array#sort, but returns +self+ with its elements sorted in place.
3384 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3388 rb_ary_sort_bang(VALUE ary
)
3391 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3392 if (RARRAY_LEN(ary
) > 1) {
3393 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3394 struct ary_sort_data data
;
3395 long len
= RARRAY_LEN(ary
);
3396 RBASIC_CLEAR_CLASS(tmp
);
3398 data
.receiver
= ary
;
3399 RARRAY_PTR_USE(tmp
, ptr
, {
3400 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3401 rb_block_given_p()?sort_1
:sort_2
, &data
);
3402 }); /* WB: no new reference */
3404 if (ARY_EMBED_P(tmp
)) {
3405 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3406 rb_ary_unshare(ary
);
3409 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3410 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3412 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3413 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3416 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3417 FL_UNSET_SHARED(ary
);
3418 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3421 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3422 if (ARY_EMBED_P(ary
)) {
3423 FL_UNSET_EMBED(ary
);
3425 else if (ARY_SHARED_P(ary
)) {
3426 /* ary might be destructively operated in the given block */
3427 rb_ary_unshare(ary
);
3432 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3433 ARY_SET_HEAP_LEN(ary
, len
);
3434 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3436 /* tmp was lost ownership for the ptr */
3437 FL_UNSET(tmp
, FL_FREEZE
);
3439 ARY_SET_EMBED_LEN(tmp
, 0);
3440 FL_SET(tmp
, FL_FREEZE
);
3442 /* tmp will be GC'ed. */
3443 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3452 * sort {|a, b| ... } -> new_array
3454 * Returns a new array containing the elements of +self+, sorted.
3456 * With no block given, compares elements using operator <tt>#<=></tt>
3459 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3461 * With a block given, calls the block with each combination of pairs of elements from +self+;
3462 * for each pair +a+ and +b+, the block should return a numeric:
3464 * - Negative when +b+ is to follow +a+.
3465 * - Zero when +a+ and +b+ are equivalent.
3466 * - Positive when +a+ is to follow +b+.
3471 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3472 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3474 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3475 * and may be unstable.
3477 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3481 rb_ary_sort(VALUE ary
)
3483 ary
= rb_ary_dup(ary
);
3484 rb_ary_sort_bang(ary
);
3488 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3492 * bsearch {|element| ... } -> found_element or nil
3493 * bsearch -> new_enumerator
3495 * Returns the element from +self+ found by a binary search,
3496 * or +nil+ if the search found no suitable element.
3498 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3500 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3504 rb_ary_bsearch(VALUE ary
)
3506 VALUE index_result
= rb_ary_bsearch_index(ary
);
3508 if (FIXNUM_P(index_result
)) {
3509 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3511 return index_result
;
3516 * bsearch_index {|element| ... } -> integer or nil
3517 * bsearch_index -> new_enumerator
3519 * Returns the integer index of the element from +self+ found by a binary search,
3520 * or +nil+ if the search found no suitable element.
3522 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3524 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3528 rb_ary_bsearch_index(VALUE ary
)
3530 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3531 int smaller
= 0, satisfied
= 0;
3534 RETURN_ENUMERATOR(ary
, 0, 0);
3535 while (low
< high
) {
3536 mid
= low
+ ((high
- low
) / 2);
3537 val
= rb_ary_entry(ary
, mid
);
3540 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3541 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3543 else if (v
== Qtrue
) {
3547 else if (!RTEST(v
)) {
3550 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3551 const VALUE zero
= INT2FIX(0);
3552 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3553 case 0: return INT2FIX(mid
);
3554 case 1: smaller
= 0; break;
3555 case -1: smaller
= 1;
3559 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3560 " (must be numeric, true, false or nil)",
3570 if (!satisfied
) return Qnil
;
3571 return INT2FIX(low
);
3576 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3583 * sort_by! {|element| ... } -> self
3584 * sort_by! -> new_enumerator
3586 * With a block given, sorts the elements of +self+ in place;
3589 * Calls the block with each successive element;
3590 * sorts elements based on the values returned from the block:
3592 * a = ['aaaa', 'bbb', 'cc', 'd']
3593 * a.sort_by! {|element| element.size }
3594 * a # => ["d", "cc", "bbb", "aaaa"]
3596 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3598 * With no block given, returns a new Enumerator.
3600 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3604 rb_ary_sort_by_bang(VALUE ary
)
3608 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3610 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3611 rb_ary_replace(ary
, sorted
);
3618 * collect {|element| ... } -> new_array
3619 * collect -> new_enumerator
3620 * map {|element| ... } -> new_array
3621 * map -> new_enumerator
3623 * With a block given, calls the block with each element of +self+;
3624 * returns a new array whose elements are the return values from the block:
3626 * a = [:foo, 'bar', 2]
3627 * a1 = a.map {|element| element.class }
3628 * a1 # => [Symbol, String, Integer]
3630 * With no block given, returns a new Enumerator.
3632 * Related: #collect!;
3633 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3637 rb_ary_collect(VALUE ary
)
3642 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3643 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3644 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3645 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3653 * collect! {|element| ... } -> new_array
3654 * collect! -> new_enumerator
3655 * map! {|element| ... } -> new_array
3656 * map! -> new_enumerator
3658 * With a block given, calls the block with each element of +self+
3659 * and replaces the element with the block's return value;
3662 * a = [:foo, 'bar', 2]
3663 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3665 * With no block given, returns a new Enumerator.
3667 * Related: #collect;
3668 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3672 rb_ary_collect_bang(VALUE ary
)
3676 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3678 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3679 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3685 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3687 VALUE result
= rb_ary_new2(argc
);
3688 long beg
, len
, i
, j
;
3690 for (i
=0; i
<argc
; i
++) {
3691 if (FIXNUM_P(argv
[i
])) {
3692 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3695 /* check if idx is Range */
3696 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3697 long end
= olen
< beg
+len
? olen
: beg
+len
;
3698 for (j
= beg
; j
< end
; j
++) {
3699 rb_ary_push(result
, (*func
)(obj
, j
));
3702 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3705 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3711 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3714 if (FIXNUM_P(idx
)) {
3715 beg
= FIX2LONG(idx
);
3717 /* check if idx is Range */
3718 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3720 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3721 const long end
= beg
+ len
;
3722 const long prevlen
= RARRAY_LEN(result
);
3724 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3727 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3733 beg
= NUM2LONG(idx
);
3735 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3740 * values_at(*specifiers) -> new_array
3742 * Returns elements from +self+ in a new array; does not modify +self+.
3744 * The objects included in the returned array are the elements of +self+
3745 * selected by the given +specifiers+,
3746 * each of which must be a numeric index or a Range.
3750 * a = ['a', 'b', 'c', 'd']
3752 * # Index specifiers.
3753 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3754 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3755 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3757 * # Range specifiers.
3758 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
3759 * a.values_at(1...3) # => ["b", "c"] # End excluded.
3760 * a.values_at(3..1) # => [] # No such elements.
3762 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
3763 * a.values_at(-50..3) # Raises RangeError.
3765 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
3766 * a.values_at(1..-50) # => [] # No such elements.
3768 * # Mixture of specifiers.
3769 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
3771 * With no +specifiers+ given, returns a new empty array:
3773 * a = ['a', 'b', 'c', 'd']
3774 * a.values_at # => []
3776 * For each numeric specifier +index+, includes an element:
3778 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
3779 * includes the element at offset +index+:
3781 * a.values_at(0, 2) # => ["a", "c"]
3782 * a.values_at(0.1, 2.9) # => ["a", "c"]
3784 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
3785 * counts backwards from the end of +self+:
3787 * a.values_at(-1, -4) # => ["d", "a"]
3789 * The given indexes may be in any order, and may repeat:
3791 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
3793 * For each +index+ that is out-of-range, includes +nil+:
3795 * a.values_at(4, -5) # => [nil, nil]
3797 * For each Range specifier +range+, includes elements
3798 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
3800 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
3801 * are non-negative and in-range (less than <tt>self.size</tt>),
3802 * includes elements from index <tt>range.begin</tt>
3803 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
3804 * or through <tt>range.end</tt> (otherwise):
3806 * a.values_at(1..2) # => ["b", "c"]
3807 * a.values_at(1...2) # => ["b"]
3809 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
3810 * counts backwards from the end of +self+:
3812 * a.values_at(-2..3) # => ["c", "d"]
3814 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
3816 * a.values_at(-5..3) # Raises RangeError.
3818 * - If <tt>range.end</tt> is positive and out-of-range,
3819 * extends the returned array with +nil+ elements:
3821 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
3823 * - If <tt>range.end</tt> is negative and in-range,
3824 * counts backwards from the end of +self+:
3826 * a.values_at(1..-2) # => ["b", "c"]
3828 * - If <tt>range.end</tt> is negative and out-of-range,
3829 * returns an empty array:
3831 * a.values_at(1..-5) # => []
3833 * The given ranges may be in any order and may repeat:
3835 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
3837 * The given specifiers may be any mixture of indexes and ranges:
3839 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
3841 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3845 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3847 long i
, olen
= RARRAY_LEN(ary
);
3848 VALUE result
= rb_ary_new_capa(argc
);
3849 for (i
= 0; i
< argc
; ++i
) {
3850 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3859 * select {|element| ... } -> new_array
3860 * select -> new_enumerator
3861 * filter {|element| ... } -> new_array
3862 * filter -> new_enumerator
3864 * With a block given, calls the block with each element of +self+;
3865 * returns a new array containing those elements of +self+
3866 * for which the block returns a truthy value:
3868 * a = [:foo, 'bar', 2, :bam]
3869 * a.select {|element| element.to_s.start_with?('b') }
3870 * # => ["bar", :bam]
3872 * With no block given, returns a new Enumerator.
3874 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3878 rb_ary_select(VALUE ary
)
3883 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3884 result
= rb_ary_new2(RARRAY_LEN(ary
));
3885 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3886 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3887 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3893 struct select_bang_arg
{
3899 select_bang_i(VALUE a
)
3901 volatile struct select_bang_arg
*arg
= (void *)a
;
3902 VALUE ary
= arg
->ary
;
3905 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3906 VALUE v
= RARRAY_AREF(ary
, i1
);
3907 if (!RTEST(rb_yield(v
))) continue;
3909 rb_ary_store(ary
, i2
, v
);
3913 return (i1
== i2
) ? Qnil
: ary
;
3917 select_bang_ensure(VALUE a
)
3919 volatile struct select_bang_arg
*arg
= (void *)a
;
3920 VALUE ary
= arg
->ary
;
3921 long len
= RARRAY_LEN(ary
);
3922 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3924 if (i2
< len
&& i2
< i1
) {
3929 RARRAY_PTR_USE(ary
, ptr
, {
3930 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3933 ARY_SET_LEN(ary
, i2
+ tail
);
3940 * select! {|element| ... } -> self or nil
3941 * select! -> new_enumerator
3942 * filter! {|element| ... } -> self or nil
3943 * filter! -> new_enumerator
3945 * With a block given, calls the block with each element of +self+;
3946 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3948 * Returns +self+ if any elements were removed:
3950 * a = [:foo, 'bar', 2, :bam]
3951 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3953 * Returns +nil+ if no elements were removed.
3955 * With no block given, returns a new Enumerator.
3957 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3961 rb_ary_select_bang(VALUE ary
)
3963 struct select_bang_arg args
;
3965 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3969 args
.len
[0] = args
.len
[1] = 0;
3970 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3975 * keep_if {|element| ... } -> self
3976 * keep_if -> new_enumerator
3978 * With a block given, calls the block with each element of +self+;
3979 * removes the element from +self+ if the block does not return a truthy value:
3981 * a = [:foo, 'bar', 2, :bam]
3982 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3984 * With no block given, returns a new Enumerator.
3986 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3990 rb_ary_keep_if(VALUE ary
)
3992 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3993 rb_ary_select_bang(ary
);
3998 ary_resize_smaller(VALUE ary
, long len
)
4001 if (RARRAY_LEN(ary
) > len
) {
4002 ARY_SET_LEN(ary
, len
);
4003 if (len
* 2 < ARY_CAPA(ary
) &&
4004 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
4005 ary_resize_capa(ary
, len
* 2);
4012 * delete(object) -> last_removed_object
4013 * delete(object) {|element| ... } -> last_removed_object or block_return
4015 * Removes zero or more elements from +self+.
4017 * With no block given,
4018 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4019 * returns the last removed element:
4021 * a = [0, 1, 2, 2.0]
4022 * a.delete(2) # => 2.0
4025 * Returns +nil+ if no elements removed:
4027 * a.delete(2) # => nil
4029 * With a block given,
4030 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4032 * If any such elements are found, ignores the block
4033 * and returns the last removed element:
4035 * a = [0, 1, 2, 2.0]
4036 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4039 * If no such element is found, returns the block's return value:
4041 * a.delete(2) {|element| "Element #{element} not found." }
4042 * # => "Element 2 not found."
4044 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4048 rb_ary_delete(VALUE ary
, VALUE item
)
4053 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4054 VALUE e
= RARRAY_AREF(ary
, i1
);
4056 if (rb_equal(e
, item
)) {
4061 rb_ary_store(ary
, i2
, e
);
4065 if (RARRAY_LEN(ary
) == i2
) {
4066 if (rb_block_given_p()) {
4067 return rb_yield(item
);
4072 ary_resize_smaller(ary
, i2
);
4079 rb_ary_delete_same(VALUE ary
, VALUE item
)
4083 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4084 VALUE e
= RARRAY_AREF(ary
, i1
);
4090 rb_ary_store(ary
, i2
, e
);
4094 if (RARRAY_LEN(ary
) == i2
) {
4098 ary_resize_smaller(ary
, i2
);
4102 rb_ary_delete_at(VALUE ary
, long pos
)
4104 long len
= RARRAY_LEN(ary
);
4107 if (pos
>= len
) return Qnil
;
4110 if (pos
< 0) return Qnil
;
4114 del
= RARRAY_AREF(ary
, pos
);
4115 RARRAY_PTR_USE(ary
, ptr
, {
4116 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4118 ARY_INCREASE_LEN(ary
, -1);
4125 * delete_at(index) -> removed_object or nil
4127 * Removes the element of +self+ at the given +index+, which must be an
4128 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4130 * When +index+ is non-negative, deletes the element at offset +index+:
4132 * a = [:foo, 'bar', 2]
4133 * a.delete_at(1) # => "bar"
4136 * When +index+ is negative, counts backward from the end of the array:
4138 * a = [:foo, 'bar', 2]
4139 * a.delete_at(-2) # => "bar"
4142 * When +index+ is out of range, returns +nil+.
4144 * a = [:foo, 'bar', 2]
4145 * a.delete_at(3) # => nil
4146 * a.delete_at(-4) # => nil
4148 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4152 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4154 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4158 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4160 const long orig_len
= RARRAY_LEN(ary
);
4165 else if (pos
< -orig_len
) {
4171 else if (orig_len
< pos
) {
4174 if (orig_len
< pos
+ len
) {
4175 len
= orig_len
- pos
;
4178 return rb_ary_new2(0);
4181 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4182 rb_ary_splice(ary
, pos
, len
, 0, 0);
4189 * slice!(index) -> object or nil
4190 * slice!(start, length) -> new_array or nil
4191 * slice!(range) -> new_array or nil
4193 * Removes and returns elements from +self+.
4195 * With numeric argument +index+ given,
4196 * removes and returns the element at offset +index+:
4198 * a = ['a', 'b', 'c', 'd']
4199 * a.slice!(2) # => "c"
4200 * a # => ["a", "b", "d"]
4201 * a.slice!(2.1) # => "d"
4204 * If +index+ is negative, counts backwards from the end of +self+:
4206 * a = ['a', 'b', 'c', 'd']
4207 * a.slice!(-2) # => "c"
4208 * a # => ["a", "b", "d"]
4210 * If +index+ is out of range, returns +nil+.
4212 * With numeric arguments +start+ and +length+ given,
4213 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4214 * returns the removed objects in a new array:
4216 * a = ['a', 'b', 'c', 'd']
4217 * a.slice!(1, 2) # => ["b", "c"]
4219 * a.slice!(0.1, 1.1) # => ["a"]
4222 * If +start+ is negative, counts backwards from the end of +self+:
4224 * a = ['a', 'b', 'c', 'd']
4225 * a.slice!(-2, 1) # => ["c"]
4226 * a # => ["a", "b", "d"]
4228 * If +start+ is out-of-range, returns +nil+:
4230 * a = ['a', 'b', 'c', 'd']
4231 * a.slice!(5, 1) # => nil
4232 * a.slice!(-5, 1) # => nil
4234 * If <tt>start + length</tt> exceeds the array size,
4235 * removes and returns all elements from offset +start+ to the end:
4237 * a = ['a', 'b', 'c', 'd']
4238 * a.slice!(2, 50) # => ["c", "d"]
4241 * If <tt>start == a.size</tt> and +length+ is non-negative,
4242 * returns a new empty array.
4244 * If +length+ is negative, returns +nil+.
4246 * With Range argument +range+ given,
4247 * treats <tt>range.min</tt> as +start+ (as above)
4248 * and <tt>range.size</tt> as +length+ (as above):
4250 * a = ['a', 'b', 'c', 'd']
4251 * a.slice!(1..2) # => ["b", "c"]
4254 * If <tt>range.start == a.size</tt>, returns a new empty array:
4256 * a = ['a', 'b', 'c', 'd']
4257 * a.slice!(4..5) # => []
4259 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4261 * a = ['a', 'b', 'c', 'd']
4262 a.slice!(5..6) # => nil
4264 * If <tt>range.start</tt> is negative,
4265 * calculates the start index by counting backwards from the end of +self+:
4267 * a = ['a', 'b', 'c', 'd']
4268 * a.slice!(-2..2) # => ["c"]
4270 * If <tt>range.end</tt> is negative,
4271 * calculates the end index by counting backwards from the end of +self+:
4273 * a = ['a', 'b', 'c', 'd']
4274 * a.slice!(0..-2) # => ["a", "b", "c"]
4276 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4280 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4285 rb_ary_modify_check(ary
);
4286 rb_check_arity(argc
, 1, 2);
4290 pos
= NUM2LONG(argv
[0]);
4291 len
= NUM2LONG(argv
[1]);
4292 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4295 if (!FIXNUM_P(arg1
)) {
4296 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4299 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4309 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4313 ary_reject(VALUE orig
, VALUE result
)
4317 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4318 VALUE v
= RARRAY_AREF(orig
, i
);
4320 if (!RTEST(rb_yield(v
))) {
4321 rb_ary_push(result
, v
);
4328 reject_bang_i(VALUE a
)
4330 volatile struct select_bang_arg
*arg
= (void *)a
;
4331 VALUE ary
= arg
->ary
;
4334 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4335 VALUE v
= RARRAY_AREF(ary
, i1
);
4336 if (RTEST(rb_yield(v
))) continue;
4338 rb_ary_store(ary
, i2
, v
);
4342 return (i1
== i2
) ? Qnil
: ary
;
4346 ary_reject_bang(VALUE ary
)
4348 struct select_bang_arg args
;
4349 rb_ary_modify_check(ary
);
4351 args
.len
[0] = args
.len
[1] = 0;
4352 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4357 * reject! {|element| ... } -> self or nil
4358 * reject! -> new_enumerator
4360 * With a block given, calls the block with each element of +self+;
4361 * removes each element for which the block returns a truthy value.
4363 * Returns +self+ if any elements removed:
4365 * a = [:foo, 'bar', 2, 'bat']
4366 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4368 * Returns +nil+ if no elements removed.
4370 * With no block given, returns a new Enumerator.
4372 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4376 rb_ary_reject_bang(VALUE ary
)
4378 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4380 return ary_reject_bang(ary
);
4385 * reject {|element| ... } -> new_array
4386 * reject -> new_enumerator
4388 * With a block given, returns a new array whose elements are all those from +self+
4389 * for which the block returns +false+ or +nil+:
4391 * a = [:foo, 'bar', 2, 'bat']
4392 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4395 * With no block given, returns a new Enumerator.
4397 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4401 rb_ary_reject(VALUE ary
)
4405 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4406 rejected_ary
= rb_ary_new();
4407 ary_reject(ary
, rejected_ary
);
4408 return rejected_ary
;
4413 * delete_if {|element| ... } -> self
4414 * delete_if -> new_numerator
4416 * With a block given, calls the block with each element of +self+;
4417 * removes the element if the block returns a truthy value;
4420 * a = [:foo, 'bar', 2, 'bat']
4421 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4423 * With no block given, returns a new Enumerator.
4425 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4429 rb_ary_delete_if(VALUE ary
)
4432 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4433 ary_reject_bang(ary
);
4438 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4440 VALUE
*args
= (VALUE
*)cbarg
;
4441 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4442 rb_ary_push(args
[0], val
);
4443 if (--args
[1] == 0) rb_iter_break();
4448 take_items(VALUE obj
, long n
)
4450 VALUE result
= rb_check_array_type(obj
);
4453 if (n
== 0) return result
;
4454 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4455 result
= rb_ary_new2(n
);
4456 args
[0] = result
; args
[1] = (VALUE
)n
;
4457 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4458 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4466 * zip(*other_arrays) -> new_array
4467 * zip(*other_arrays) {|sub_array| ... } -> nil
4469 * With no block given, combines +self+ with the collection of +other_arrays+;
4470 * returns a new array of sub-arrays:
4472 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4473 * # => [[0, "zero", :zero], [1, "one", :one]]
4477 * - The outer array is of size <tt>self.size</tt>.
4478 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4479 * - The _nth_ sub-array contains (in order):
4481 * - The _nth_ element of +self+.
4482 * - The _nth_ element of each of the other arrays, as available.
4487 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4488 * # => [[0, "zero", :zero], [1, "one", :one]]
4489 * zipped.size # => 2 # Same size as a.
4490 * zipped.first.size # => 3 # Size of other arrays plus 1.
4492 * When the other arrays are all the same size as +self+,
4493 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4494 * (including +self+), with no omissions or additions:
4496 * a = [:a0, :a1, :a2, :a3]
4497 * b = [:b0, :b1, :b2, :b3]
4498 * c = [:c0, :c1, :c2, :c3]
4507 * When one of the other arrays is smaller than +self+,
4508 * pads the corresponding sub-array with +nil+ elements:
4510 * a = [:a0, :a1, :a2, :a3]
4511 * b = [:b0, :b1, :b2]
4521 * When one of the other arrays is larger than +self+,
4522 * _ignores_ its trailing elements:
4524 * a = [:a0, :a1, :a2, :a3]
4525 * b = [:b0, :b1, :b2, :b3, :b4]
4526 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4535 * With a block given, calls the block with each of the other arrays;
4539 * a = [:a0, :a1, :a2, :a3]
4540 * b = [:b0, :b1, :b2, :b3]
4541 * c = [:c0, :c1, :c2, :c3]
4542 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4550 * For an *object* in *other_arrays* that is not actually an array,
4551 * forms the the "other array" as <tt>object.to_ary</tt>, if defined,
4552 * or as <tt>object.each.to_a</tt> otherwise.
4554 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4558 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4561 long len
= RARRAY_LEN(ary
);
4562 VALUE result
= Qnil
;
4564 for (i
=0; i
<argc
; i
++) {
4565 argv
[i
] = take_items(argv
[i
], len
);
4568 if (rb_block_given_p()) {
4569 int arity
= rb_block_arity();
4574 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4576 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4577 tmp
[0] = RARRAY_AREF(ary
, i
);
4578 for (j
=0; j
<argc
; j
++) {
4579 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4581 rb_yield_values2(argc
+1, tmp
);
4584 if (work
) ALLOCV_END(work
);
4587 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4588 VALUE tmp
= rb_ary_new2(argc
+1);
4590 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4591 for (j
=0; j
<argc
; j
++) {
4592 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4599 result
= rb_ary_new_capa(len
);
4601 for (i
=0; i
<len
; i
++) {
4602 VALUE tmp
= rb_ary_new_capa(argc
+1);
4604 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4605 for (j
=0; j
<argc
; j
++) {
4606 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4608 rb_ary_push(result
, tmp
);
4617 * transpose -> new_array
4619 * Returns a new array that is +self+
4620 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4622 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4623 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4625 * The elements of +self+ must all be the same size.
4627 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4631 rb_ary_transpose(VALUE ary
)
4633 long elen
= -1, alen
, i
, j
;
4634 VALUE tmp
, result
= 0;
4636 alen
= RARRAY_LEN(ary
);
4637 if (alen
== 0) return rb_ary_dup(ary
);
4638 for (i
=0; i
<alen
; i
++) {
4639 tmp
= to_ary(rb_ary_elt(ary
, i
));
4640 if (elen
< 0) { /* first element */
4641 elen
= RARRAY_LEN(tmp
);
4642 result
= rb_ary_new2(elen
);
4643 for (j
=0; j
<elen
; j
++) {
4644 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4647 else if (elen
!= RARRAY_LEN(tmp
)) {
4648 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4649 RARRAY_LEN(tmp
), elen
);
4651 for (j
=0; j
<elen
; j
++) {
4652 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4660 * initialize_copy(other_array) -> self
4661 * replace(other_array) -> self
4663 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4664 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4667 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4668 * a.replace(['d', 'e']) # => ["d", "e"]
4670 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4674 rb_ary_replace(VALUE copy
, VALUE orig
)
4676 rb_ary_modify_check(copy
);
4677 orig
= to_ary(orig
);
4678 if (copy
== orig
) return copy
;
4682 /* orig has enough space to embed the contents of orig. */
4683 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4684 RUBY_ASSERT(ARY_EMBED_P(copy
));
4685 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4686 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4688 /* orig is embedded but copy does not have enough space to embed the
4689 * contents of orig. */
4690 else if (ARY_EMBED_P(orig
)) {
4691 long len
= ARY_EMBED_LEN(orig
);
4692 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4694 FL_UNSET_EMBED(copy
);
4695 ARY_SET_PTR(copy
, ptr
);
4696 ARY_SET_LEN(copy
, len
);
4697 ARY_SET_CAPA(copy
, len
);
4699 // No allocation and exception expected that could leave `copy` in a
4700 // bad state from the edits above.
4701 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4703 /* Otherwise, orig is on heap and copy does not have enough space to embed
4704 * the contents of orig. */
4706 VALUE shared_root
= ary_make_shared(orig
);
4707 FL_UNSET_EMBED(copy
);
4708 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4709 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4710 rb_ary_set_shared(copy
, shared_root
);
4720 * Removes all elements from +self+; returns +self+:
4722 * a = [:foo, 'bar', 2]
4725 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4729 rb_ary_clear(VALUE ary
)
4731 rb_ary_modify_check(ary
);
4732 if (ARY_SHARED_P(ary
)) {
4733 rb_ary_unshare(ary
);
4735 ARY_SET_EMBED_LEN(ary
, 0);
4738 ARY_SET_LEN(ary
, 0);
4739 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4740 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4749 * fill(object, start = nil, count = nil) -> new_array
4750 * fill(object, range) -> new_array
4751 * fill(start = nil, count = nil) {|element| ... } -> new_array
4752 * fill(range) {|element| ... } -> new_array
4754 * Replaces selected elements in +self+;
4755 * may add elements to +self+;
4756 * always returns +self+ (never a new array).
4760 * # Non-negative start.
4761 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4762 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4764 * # Extends with specified values if necessary.
4765 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4766 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4768 * # Fills with nils if necessary.
4769 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4770 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4772 * # For negative start, counts backwards from the end.
4773 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4774 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4777 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4778 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4780 * When arguments +start+ and +count+ are given,
4781 * they select the elements of +self+ to be replaced;
4783 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4786 * - +start+ specifies the zero-based offset of the first element to be replaced;
4788 * - +count+ is the number of consecutive elements to be replaced;
4789 * +nil+ means "all the rest."
4791 * With argument +object+ given,
4792 * that one object is used for all replacements:
4794 * o = Object.new # => #<Object:0x0000014e7bff7600>
4795 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4797 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4799 * With a block given, the block is called once for each element to be replaced;
4800 * the value passed to the block is the _index_ of the element to be replaced
4801 * (not the element itself);
4802 * the block's return value replaces the element:
4804 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4805 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4807 * For arguments +start+ and +count+:
4809 * - If +start+ is non-negative,
4810 * replaces +count+ elements beginning at offset +start+:
4812 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4813 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4814 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4816 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4817 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4818 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4820 * Extends +self+ if necessary:
4822 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4823 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4825 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4826 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4828 * Fills with +nil+ if necessary:
4830 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4831 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4833 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4834 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4836 * Does nothing if +count+ is non-positive:
4838 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4839 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4840 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4842 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4843 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4844 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4846 * - If +start+ is negative, counts backwards from the end of +self+:
4848 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4849 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4851 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4852 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4854 * Extends +self+ if necessary:
4856 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4857 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4859 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4860 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4862 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4864 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4865 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4867 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4868 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4870 * Does nothing if +count+ is non-positive:
4872 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4873 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4875 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4876 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4878 * When argument +range+ is given,
4879 * it must be a Range object whose members are numeric;
4880 * its +begin+ and +end+ values determine the elements of +self+
4883 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4886 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4887 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4889 * If +end+ is smaller than +begin+, replaces no elements:
4891 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4892 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4894 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4896 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4897 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4898 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4900 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4901 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4902 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4904 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4906 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4907 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4909 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4910 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4912 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4913 * replaces elements to the end of +self+:
4915 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4916 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4918 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4919 * replaces elements from the beginning of +self+:
4921 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4922 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4924 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4928 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4930 VALUE item
= Qundef
, arg1
, arg2
;
4931 long beg
= 0, end
= 0, len
= 0;
4933 if (rb_block_given_p()) {
4934 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4935 argc
+= 1; /* hackish */
4938 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4943 len
= RARRAY_LEN(ary
);
4946 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4951 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4953 beg
= RARRAY_LEN(ary
) + beg
;
4954 if (beg
< 0) beg
= 0;
4956 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4963 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4964 rb_raise(rb_eArgError
, "argument too big");
4967 if (RARRAY_LEN(ary
) < end
) {
4968 if (end
>= ARY_CAPA(ary
)) {
4969 ary_resize_capa(ary
, end
);
4971 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4972 ARY_SET_LEN(ary
, end
);
4975 if (UNDEF_P(item
)) {
4979 for (i
=beg
; i
<end
; i
++) {
4980 v
= rb_yield(LONG2NUM(i
));
4981 if (i
>=RARRAY_LEN(ary
)) break;
4986 ary_memfill(ary
, beg
, len
, item
);
4993 * self + other_array -> new_array
4995 * Returns a new array containing all elements of +self+
4996 * followed by all elements of +other_array+:
4998 * a = [0, 1] + [2, 3]
4999 * a # => [0, 1, 2, 3]
5001 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5005 rb_ary_plus(VALUE x
, VALUE y
)
5008 long len
, xlen
, ylen
;
5011 xlen
= RARRAY_LEN(x
);
5012 ylen
= RARRAY_LEN(y
);
5014 z
= rb_ary_new2(len
);
5016 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
5017 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
5018 ARY_SET_LEN(z
, len
);
5023 ary_append(VALUE x
, VALUE y
)
5025 long n
= RARRAY_LEN(y
);
5027 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
5035 * concat(*other_arrays) -> self
5037 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5040 * a.concat(['two', 'three'], [:four, :five], a)
5041 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5043 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5047 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
5049 rb_ary_modify_check(ary
);
5052 rb_ary_concat(ary
, argv
[0]);
5054 else if (argc
> 1) {
5056 VALUE args
= rb_ary_hidden_new(argc
);
5057 for (i
= 0; i
< argc
; i
++) {
5058 rb_ary_concat(args
, argv
[i
]);
5060 ary_append(ary
, args
);
5068 rb_ary_concat(VALUE x
, VALUE y
)
5070 return ary_append(x
, to_ary(y
));
5075 * self * n -> new_array
5076 * self * string_separator -> new_string
5078 * When non-negative integer argument +n+ is given,
5079 * returns a new array built by concatenating +n+ copies of +self+:
5082 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5084 * When string argument +string_separator+ is given,
5085 * equivalent to <tt>self.join(string_separator)</tt>:
5087 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5092 rb_ary_times(VALUE ary
, VALUE times
)
5098 tmp
= rb_check_string_type(times
);
5100 return rb_ary_join(ary
, tmp
);
5103 len
= NUM2LONG(times
);
5105 ary2
= ary_new(rb_cArray
, 0);
5109 rb_raise(rb_eArgError
, "negative argument");
5111 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
5112 rb_raise(rb_eArgError
, "argument too big");
5114 len
*= RARRAY_LEN(ary
);
5116 ary2
= ary_new(rb_cArray
, len
);
5117 ARY_SET_LEN(ary2
, len
);
5119 ptr
= RARRAY_CONST_PTR(ary
);
5120 t
= RARRAY_LEN(ary
);
5122 ary_memcpy(ary2
, 0, t
, ptr
);
5123 while (t
<= len
/2) {
5124 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5128 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5137 * assoc(object) -> found_array or nil
5139 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5140 * and <tt>ele[0] == object</tt>:
5142 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5143 * a.assoc(4) # => [4, 5, 6]
5145 * Returns +nil+ if no such element is found.
5147 * Related: Array#rassoc;
5148 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5152 rb_ary_assoc(VALUE ary
, VALUE key
)
5157 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5158 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5159 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5160 rb_equal(RARRAY_AREF(v
, 0), key
))
5168 * rassoc(object) -> found_array or nil
5170 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5171 * and <tt>ele[1] == object</tt>:
5173 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5174 * a.rassoc(4) # => [2, 4]
5175 * a.rassoc(5) # => [4, 5, 6]
5177 * Returns +nil+ if no such element is found.
5179 * Related: Array#assoc;
5180 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5184 rb_ary_rassoc(VALUE ary
, VALUE value
)
5189 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5190 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5191 if (RB_TYPE_P(v
, T_ARRAY
) &&
5192 RARRAY_LEN(v
) > 1 &&
5193 rb_equal(RARRAY_AREF(v
, 1), value
))
5200 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5203 const VALUE
*p1
, *p2
;
5205 if (recur
) return Qtrue
; /* Subtle! */
5207 /* rb_equal() can evacuate ptrs */
5208 p1
= RARRAY_CONST_PTR(ary1
);
5209 p2
= RARRAY_CONST_PTR(ary2
);
5210 len1
= RARRAY_LEN(ary1
);
5212 for (i
= 0; i
< len1
; i
++) {
5214 if (rb_equal(*p1
, *p2
)) {
5215 len1
= RARRAY_LEN(ary1
);
5216 if (len1
!= RARRAY_LEN(ary2
))
5220 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5221 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5235 * self == other_array -> true or false
5237 * Returns whether both:
5239 * - +self+ and +other_array+ are the same size.
5240 * - Their corresponding elements are the same;
5241 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5242 * <tt>self[i] == other_array[i]</tt>.
5246 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5247 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5248 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5249 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5251 * This method is different from method Array#eql?,
5252 * which compares elements using <tt>Object#eql?</tt>.
5254 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5258 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5260 if (ary1
== ary2
) return Qtrue
;
5261 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5262 if (!rb_respond_to(ary2
, idTo_ary
)) {
5265 return rb_equal(ary2
, ary1
);
5267 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5268 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5269 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5273 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5277 if (recur
) return Qtrue
; /* Subtle! */
5278 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5279 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5287 * eql?(other_array) -> true or false
5289 * Returns +true+ if +self+ and +other_array+ are the same size,
5290 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5292 * a0 = [:foo, 'bar', 2]
5293 * a1 = [:foo, 'bar', 2]
5294 * a1.eql?(a0) # => true
5296 * Otherwise, returns +false+.
5298 * This method is different from method Array#==,
5299 * which compares using method <tt>Object#==</tt>.
5301 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5305 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5307 if (ary1
== ary2
) return Qtrue
;
5308 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5309 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5310 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5311 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5315 rb_ary_hash_values(long len
, const VALUE
*elements
)
5321 h
= rb_hash_start(len
);
5322 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5323 for (i
=0; i
<len
; i
++) {
5324 n
= rb_hash(elements
[i
]);
5325 h
= rb_hash_uint(h
, NUM2LONG(n
));
5335 * Returns the integer hash value for +self+.
5337 * Two arrays with the same content will have the same hash value
5338 * (and will compare using eql?):
5340 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5341 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5342 * ['a', 'b'].hash == ['a'].hash # => false
5347 rb_ary_hash(VALUE ary
)
5349 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5354 * include?(object) -> true or false
5356 * Returns whether for some element +element+ in +self+,
5357 * <tt>object == element</tt>:
5359 * [0, 1, 2].include?(2) # => true
5360 * [0, 1, 2].include?(2.0) # => true
5361 * [0, 1, 2].include?(2.1) # => false
5363 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5367 rb_ary_includes(VALUE ary
, VALUE item
)
5372 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5373 e
= RARRAY_AREF(ary
, i
);
5374 if (rb_equal(e
, item
)) {
5382 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5387 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5388 e
= RARRAY_AREF(ary
, i
);
5389 if (rb_eql(item
, e
)) {
5397 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5401 if (recur
) return Qundef
; /* Subtle! */
5402 len
= RARRAY_LEN(ary1
);
5403 if (len
> RARRAY_LEN(ary2
)) {
5404 len
= RARRAY_LEN(ary2
);
5406 for (i
=0; i
<len
; i
++) {
5407 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5408 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5409 if (v
!= INT2FIX(0)) {
5418 * self <=> other_array -> -1, 0, or 1
5420 * Returns -1, 0, or 1 as +self+ is determined
5421 * to be less than, equal to, or greater than +other_array+.
5423 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5425 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5426 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5428 * [0, 1, 2] <=> [0, 0, 2] # => 1
5430 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5432 * [0, 1, 2] <=> [0, 2, 2] # => -1
5434 * - Continues if <tt>result[i]</tt> is 0.
5436 * When every +result+ is 0,
5437 * returns <tt>self.size <=> other_array.size</tt>
5438 * (see Integer#<=>):
5440 * [0, 1, 2] <=> [0, 1] # => 1
5441 * [0, 1, 2] <=> [0, 1, 2] # => 0
5442 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5444 * Note that when +other_array+ is larger than +self+,
5445 * its trailing elements do not affect the result:
5447 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5448 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5449 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5451 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5455 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5460 ary2
= rb_check_array_type(ary2
);
5461 if (NIL_P(ary2
)) return Qnil
;
5462 if (ary1
== ary2
) return INT2FIX(0);
5463 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5464 if (!UNDEF_P(v
)) return v
;
5465 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5466 if (len
== 0) return INT2FIX(0);
5467 if (len
> 0) return INT2FIX(1);
5472 ary_add_hash(VALUE hash
, VALUE ary
)
5476 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5477 VALUE elt
= RARRAY_AREF(ary
, i
);
5478 rb_hash_add_new_element(hash
, elt
, elt
);
5484 ary_tmp_hash_new(VALUE ary
)
5486 long size
= RARRAY_LEN(ary
);
5487 VALUE hash
= rb_hash_new_with_size(size
);
5489 RBASIC_CLEAR_CLASS(hash
);
5494 ary_make_hash(VALUE ary
)
5496 VALUE hash
= ary_tmp_hash_new(ary
);
5497 return ary_add_hash(hash
, ary
);
5501 ary_add_hash_by(VALUE hash
, VALUE ary
)
5505 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5506 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5507 rb_hash_add_new_element(hash
, k
, v
);
5513 ary_make_hash_by(VALUE ary
)
5515 VALUE hash
= ary_tmp_hash_new(ary
);
5516 return ary_add_hash_by(hash
, ary
);
5521 * self - other_array -> new_array
5523 * Returns a new array containing only those elements of +self+
5524 * that are not found in +other_array+;
5525 * the order from +self+ is preserved:
5527 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5528 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5529 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5531 * Element are compared using method <tt>#eql?</tt>
5532 * (as defined in each element of +self+).
5534 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5538 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5544 ary2
= to_ary(ary2
);
5545 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5546 ary3
= rb_ary_new();
5548 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5549 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5550 VALUE elt
= rb_ary_elt(ary1
, i
);
5551 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5552 rb_ary_push(ary3
, elt
);
5557 hash
= ary_make_hash(ary2
);
5558 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5559 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5560 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5568 * difference(*other_arrays = []) -> new_array
5570 * Returns a new array containing only those elements from +self+
5571 * that are not found in any of the given +other_arrays+;
5572 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5574 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5575 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5576 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5577 * [0, 1, 2].difference # => [0, 1, 2]
5579 * Returns a copy of +self+ if no arguments are given.
5582 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5586 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5591 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5592 ary_diff
= rb_ary_new();
5593 length
= RARRAY_LEN(ary
);
5595 for (i
= 0; i
< argc
; i
++) {
5596 argv
[i
] = to_ary(argv
[i
]);
5597 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5598 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5601 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5603 VALUE elt
= rb_ary_elt(ary
, i
);
5604 for (j
= 0; j
< argc
; j
++) {
5606 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5610 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5613 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5624 * self & other_array -> new_array
5626 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5627 * that is, containing those elements found in both +self+ and +other_array+:
5629 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5633 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5635 * Preserves order from +self+:
5637 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5639 * Identifies common elements using method <tt>#eql?</tt>
5640 * (as defined in each element of +self+).
5642 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5647 rb_ary_and(VALUE ary1
, VALUE ary2
)
5649 VALUE hash
, ary3
, v
;
5653 ary2
= to_ary(ary2
);
5654 ary3
= rb_ary_new();
5655 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5657 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5658 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5659 v
= RARRAY_AREF(ary1
, i
);
5660 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5661 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5662 rb_ary_push(ary3
, v
);
5667 hash
= ary_make_hash(ary2
);
5669 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5670 v
= RARRAY_AREF(ary1
, i
);
5672 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5673 rb_ary_push(ary3
, v
);
5682 * intersection(*other_arrays) -> new_array
5684 * Returns a new array containing each element in +self+ that is +#eql?+
5685 * to at least one element in each of the given +other_arrays+;
5686 * duplicates are omitted:
5688 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5690 * Each element must correctly implement method <tt>#hash</tt>.
5692 * Order from +self+ is preserved:
5694 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5696 * Returns a copy of +self+ if no arguments are given.
5698 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5702 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5704 VALUE result
= rb_ary_dup(ary
);
5707 for (i
= 0; i
< argc
; i
++) {
5708 result
= rb_ary_and(result
, argv
[i
]);
5715 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5717 if (existing
) return ST_STOP
;
5718 *key
= *value
= (VALUE
)arg
;
5723 rb_ary_union(VALUE ary_union
, VALUE ary
)
5726 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5727 VALUE elt
= rb_ary_elt(ary
, i
);
5728 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5729 rb_ary_push(ary_union
, elt
);
5734 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5737 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5738 VALUE elt
= RARRAY_AREF(ary2
, i
);
5739 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5740 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5747 * self | other_array -> new_array
5749 * Returns the union of +self+ and +other_array+;
5750 * duplicates are removed; order is preserved;
5751 * items are compared using <tt>eql?</tt>:
5753 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5754 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5755 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5757 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5761 rb_ary_or(VALUE ary1
, VALUE ary2
)
5765 ary2
= to_ary(ary2
);
5766 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5767 VALUE ary3
= rb_ary_new();
5768 rb_ary_union(ary3
, ary1
);
5769 rb_ary_union(ary3
, ary2
);
5773 hash
= ary_make_hash(ary1
);
5774 rb_ary_union_hash(hash
, ary2
);
5776 return rb_hash_values(hash
);
5781 * union(*other_arrays) -> new_array
5783 * Returns a new array that is the union of the elements of +self+
5784 * and all given arrays +other_arrays+;
5785 * items are compared using <tt>eql?</tt>:
5787 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5789 * Removes duplicates (preserving the first found):
5791 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5793 * Preserves order (preserving the position of the first found):
5795 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5797 * With no arguments given, returns a copy of +self+.
5799 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5803 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5809 sum
= RARRAY_LEN(ary
);
5810 for (i
= 0; i
< argc
; i
++) {
5811 argv
[i
] = to_ary(argv
[i
]);
5812 sum
+= RARRAY_LEN(argv
[i
]);
5815 if (sum
<= SMALL_ARRAY_LEN
) {
5816 VALUE ary_union
= rb_ary_new();
5818 rb_ary_union(ary_union
, ary
);
5819 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5824 hash
= ary_make_hash(ary
);
5825 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5827 return rb_hash_values(hash
);
5832 * intersect?(other_array) -> true or false
5834 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5836 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5837 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5839 * Each element must correctly implement method <tt>#hash</tt>.
5841 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5845 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5847 VALUE hash
, v
, result
, shorter
, longer
;
5851 ary2
= to_ary(ary2
);
5852 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5854 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5855 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5856 v
= RARRAY_AREF(ary1
, i
);
5857 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5864 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5869 hash
= ary_make_hash(shorter
);
5872 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5873 v
= RARRAY_AREF(longer
, i
);
5875 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5885 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5887 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5890 for (; i
< RARRAY_LEN(ary
); ++i
) {
5891 v
= RARRAY_AREF(ary
, i
);
5893 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5902 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5904 const long n
= RARRAY_LEN(ary
);
5905 RUBY_ASSERT(i
> 0 && i
< n
);
5906 RUBY_ASSERT(FIXNUM_P(vmax
));
5909 for (; i
< n
; ++i
) {
5910 v
= RARRAY_AREF(ary
, i
);
5913 if ((long)vmax
< (long)v
) {
5918 return ary_max_generic(ary
, i
, vmax
);
5926 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5928 const long n
= RARRAY_LEN(ary
);
5929 RUBY_ASSERT(i
> 0 && i
< n
);
5930 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5933 for (; i
< n
; ++i
) {
5934 v
= RARRAY_AREF(ary
, i
);
5936 if (RB_FLOAT_TYPE_P(v
)) {
5937 if (rb_float_cmp(vmax
, v
) < 0) {
5942 return ary_max_generic(ary
, i
, vmax
);
5950 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5952 const long n
= RARRAY_LEN(ary
);
5953 RUBY_ASSERT(i
> 0 && i
< n
);
5954 RUBY_ASSERT(STRING_P(vmax
));
5957 for (; i
< n
; ++i
) {
5958 v
= RARRAY_AREF(ary
, i
);
5961 if (rb_str_cmp(vmax
, v
) < 0) {
5966 return ary_max_generic(ary
, i
, vmax
);
5976 * max(count) -> new_array
5977 * max {|a, b| ... } -> element
5978 * max(count) {|a, b| ... } -> new_array
5980 * Returns one of the following:
5982 * - The maximum-valued element from +self+.
5983 * - A new array of maximum-valued elements from +self+.
5985 * Does not modify +self+.
5987 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5990 * With no argument and no block, returns the element in +self+
5991 * having the maximum value per method <tt>#<=></tt>:
5993 * [1, 0, 3, 2].max # => 3
5995 * With non-negative numeric argument +count+ and no block,
5996 * returns a new array with at most +count+ elements,
5997 * in descending order, per method <tt>#<=></tt>:
5999 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6000 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6001 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6002 * [1, 0, 3, 2].max(0) # => []
6004 * With a block given, the block must return a numeric.
6006 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6007 * returns the element having the maximum value per the block:
6009 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6012 * With non-negative numeric argument +count+ and a block,
6013 * returns a new array with at most +count+ elements,
6014 * in descending order, per the block:
6016 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6017 * # => ["000", "00"]
6019 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6022 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
6024 VALUE result
= Qundef
, v
;
6028 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6029 return rb_nmin_run(ary
, num
, 0, 1, 1);
6031 const long n
= RARRAY_LEN(ary
);
6032 if (rb_block_given_p()) {
6033 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6034 v
= RARRAY_AREF(ary
, i
);
6035 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
6041 result
= RARRAY_AREF(ary
, 0);
6043 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6044 return ary_max_opt_fixnum(ary
, 1, result
);
6046 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6047 return ary_max_opt_string(ary
, 1, result
);
6049 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6050 return ary_max_opt_float(ary
, 1, result
);
6053 return ary_max_generic(ary
, 1, result
);
6057 if (UNDEF_P(result
)) return Qnil
;
6062 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
6064 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
6067 for (; i
< RARRAY_LEN(ary
); ++i
) {
6068 v
= RARRAY_AREF(ary
, i
);
6070 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
6079 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
6081 const long n
= RARRAY_LEN(ary
);
6082 RUBY_ASSERT(i
> 0 && i
< n
);
6083 RUBY_ASSERT(FIXNUM_P(vmin
));
6086 for (; i
< n
; ++i
) {
6087 a
= RARRAY_AREF(ary
, i
);
6090 if ((long)vmin
> (long)a
) {
6095 return ary_min_generic(ary
, i
, vmin
);
6103 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
6105 const long n
= RARRAY_LEN(ary
);
6106 RUBY_ASSERT(i
> 0 && i
< n
);
6107 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
6110 for (; i
< n
; ++i
) {
6111 a
= RARRAY_AREF(ary
, i
);
6113 if (RB_FLOAT_TYPE_P(a
)) {
6114 if (rb_float_cmp(vmin
, a
) > 0) {
6119 return ary_min_generic(ary
, i
, vmin
);
6127 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
6129 const long n
= RARRAY_LEN(ary
);
6130 RUBY_ASSERT(i
> 0 && i
< n
);
6131 RUBY_ASSERT(STRING_P(vmin
));
6134 for (; i
< n
; ++i
) {
6135 a
= RARRAY_AREF(ary
, i
);
6138 if (rb_str_cmp(vmin
, a
) > 0) {
6143 return ary_min_generic(ary
, i
, vmin
);
6153 * min(count) -> new_array
6154 * min {|a, b| ... } -> element
6155 * min(count) {|a, b| ... } -> new_array
6157 * Returns one of the following:
6159 * - The minimum-valued element from +self+.
6160 * - A new array of minimum-valued elements from +self+.
6162 * Does not modify +self+.
6164 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6167 * With no argument and no block, returns the element in +self+
6168 * having the minimum value per method <tt>#<=></tt>:
6170 * [1, 0, 3, 2].min # => 0
6172 * With non-negative numeric argument +count+ and no block,
6173 * returns a new array with at most +count+ elements,
6174 * in ascending order, per method <tt>#<=></tt>:
6176 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6177 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6178 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6179 * [1, 0, 3, 2].min(0) # => []
6181 * With a block given, the block must return a numeric.
6183 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6184 * returns the element having the minimum value per the block:
6186 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6189 * With non-negative numeric argument +count+ and a block,
6190 * returns a new array with at most +count+ elements,
6191 * in ascending order, per the block:
6193 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6196 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6199 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6201 VALUE result
= Qundef
, v
;
6205 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6206 return rb_nmin_run(ary
, num
, 0, 0, 1);
6208 const long n
= RARRAY_LEN(ary
);
6209 if (rb_block_given_p()) {
6210 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6211 v
= RARRAY_AREF(ary
, i
);
6212 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6218 result
= RARRAY_AREF(ary
, 0);
6220 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6221 return ary_min_opt_fixnum(ary
, 1, result
);
6223 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6224 return ary_min_opt_string(ary
, 1, result
);
6226 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6227 return ary_min_opt_float(ary
, 1, result
);
6230 return ary_min_generic(ary
, 1, result
);
6234 if (UNDEF_P(result
)) return Qnil
;
6241 * minmax {|a, b| ... } -> array
6243 * Returns a 2-element array containing the minimum-valued and maximum-valued
6244 * elements from +self+;
6245 * does not modify +self+.
6247 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6249 * [1, 0, 3, 2].minmax # => [0, 3]
6251 * With a block given, the block must return a numeric;
6252 * the block is called <tt>self.size - 1</tt> times to compare elements;
6253 * returns the elements having the minimum and maximum values per the block:
6255 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6258 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6261 rb_ary_minmax(VALUE ary
)
6263 if (rb_block_given_p()) {
6264 return rb_call_super(0, NULL
);
6266 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6270 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6272 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6278 * uniq! -> self or nil
6279 * uniq! {|element| ... } -> self or nil
6281 * Removes duplicate elements from +self+, the first occurrence always being retained;
6282 * returns +self+ if any elements removed, +nil+ otherwise.
6284 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6285 * to compare elements:
6287 * a = [0, 0, 1, 1, 2, 2]
6288 * a.uniq! # => [0, 1, 2]
6291 * With a block given, calls the block for each element;
6292 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6293 * to compare <i>block return values</i>;
6294 * that is, an element is a duplicate if its block return value
6295 * is the same as that of a previous element:
6297 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6298 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6299 * a.uniq! {|element| element.size } # => nil
6301 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6304 rb_ary_uniq_bang(VALUE ary
)
6309 rb_ary_modify_check(ary
);
6310 if (RARRAY_LEN(ary
) <= 1)
6312 if (rb_block_given_p())
6313 hash
= ary_make_hash_by(ary
);
6315 hash
= ary_make_hash(ary
);
6317 hash_size
= RHASH_SIZE(hash
);
6318 if (RARRAY_LEN(ary
) == hash_size
) {
6321 rb_ary_modify_check(ary
);
6322 ARY_SET_LEN(ary
, 0);
6323 if (ARY_SHARED_P(ary
)) {
6324 rb_ary_unshare(ary
);
6327 ary_resize_capa(ary
, hash_size
);
6328 rb_hash_foreach(hash
, push_value
, ary
);
6336 * uniq {|element| ... } -> new_array
6338 * Returns a new array containing those elements from +self+ that are not duplicates,
6339 * the first occurrence always being retained.
6341 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6342 * to compare elements:
6344 * a = [0, 0, 1, 1, 2, 2]
6345 * a.uniq # => [0, 1, 2]
6347 * With a block given, calls the block for each element;
6348 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6349 * to compare <i>block return values</i>;
6350 * that is, an element is a duplicate if its block return value
6351 * is the same as that of a previous element:
6353 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6354 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6356 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6360 rb_ary_uniq(VALUE ary
)
6364 if (RARRAY_LEN(ary
) <= 1) {
6366 uniq
= rb_ary_dup(ary
);
6368 else if (rb_block_given_p()) {
6369 hash
= ary_make_hash_by(ary
);
6370 uniq
= rb_hash_values(hash
);
6373 hash
= ary_make_hash(ary
);
6374 uniq
= rb_hash_values(hash
);
6382 * compact! -> self or nil
6384 * Removes all +nil+ elements from +self+;
6385 * Returns +self+ if any elements are removed, +nil+ otherwise:
6387 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6388 * a.compact! # => [0, false, "", [], {}]
6389 * a # => [0, false, "", [], {}]
6390 * a.compact! # => nil
6392 * Related: Array#compact;
6393 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6397 rb_ary_compact_bang(VALUE ary
)
6403 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6404 end
= p
+ RARRAY_LEN(ary
);
6410 n
= p
- RARRAY_CONST_PTR(ary
);
6411 if (RARRAY_LEN(ary
) == n
) {
6414 ary_resize_smaller(ary
, n
);
6421 * compact -> new_array
6423 * Returns a new array containing only the non-+nil+ elements from +self+;
6424 * element order is preserved:
6426 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6427 * a.compact # => [0, false, "", [], {}]
6429 * Related: Array#compact!;
6430 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6434 rb_ary_compact(VALUE ary
)
6436 ary
= rb_ary_dup(ary
);
6437 rb_ary_compact_bang(ary
);
6444 * count(object) -> integer
6445 * count {|element| ... } -> integer
6447 * Returns a count of specified elements.
6449 * With no argument and no block, returns the count of all elements:
6451 * [0, :one, 'two', 3, 3.0].count # => 5
6453 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6455 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6457 * With no argument and a block given, calls the block with each element;
6458 * returns the count of elements for which the block returns a truthy value:
6460 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6462 * With argument +object+ and a block given, issues a warning, ignores the block,
6463 * and returns the count of elements <tt>==</tt> to +object+.
6465 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6469 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6473 if (rb_check_arity(argc
, 0, 1) == 0) {
6476 if (!rb_block_given_p())
6477 return LONG2NUM(RARRAY_LEN(ary
));
6479 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6480 v
= RARRAY_AREF(ary
, i
);
6481 if (RTEST(rb_yield(v
))) n
++;
6485 VALUE obj
= argv
[0];
6487 if (rb_block_given_p()) {
6488 rb_warn("given block not used");
6490 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6491 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6499 flatten(VALUE ary
, int level
)
6502 VALUE stack
, result
, tmp
= 0, elt
;
6503 VALUE memo
= Qfalse
;
6505 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6506 elt
= RARRAY_AREF(ary
, i
);
6507 tmp
= rb_check_array_type(elt
);
6512 if (i
== RARRAY_LEN(ary
)) {
6516 result
= ary_new(0, RARRAY_LEN(ary
));
6517 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6518 ARY_SET_LEN(result
, i
);
6520 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6521 rb_ary_push(stack
, ary
);
6522 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6525 memo
= rb_obj_hide(rb_ident_hash_new());
6526 rb_hash_aset(memo
, ary
, Qtrue
);
6527 rb_hash_aset(memo
, tmp
, Qtrue
);
6534 while (i
< RARRAY_LEN(ary
)) {
6535 elt
= RARRAY_AREF(ary
, i
++);
6536 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6537 rb_ary_push(result
, elt
);
6540 tmp
= rb_check_array_type(elt
);
6541 if (RBASIC(result
)->klass
) {
6543 rb_hash_clear(memo
);
6545 rb_raise(rb_eRuntimeError
, "flatten reentered");
6548 rb_ary_push(result
, elt
);
6552 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6553 rb_hash_clear(memo
);
6554 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6556 rb_hash_aset(memo
, tmp
, Qtrue
);
6558 rb_ary_push(stack
, ary
);
6559 rb_ary_push(stack
, LONG2NUM(i
));
6564 if (RARRAY_LEN(stack
) == 0) {
6568 rb_hash_delete(memo
, ary
);
6570 tmp
= rb_ary_pop(stack
);
6572 ary
= rb_ary_pop(stack
);
6576 rb_hash_clear(memo
);
6579 RBASIC_SET_CLASS(result
, rb_cArray
);
6585 * flatten!(depth = nil) -> self or nil
6587 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6588 * +depth+ must be an
6589 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6591 * At each level of recursion:
6593 * - Each element that is an array is "flattened"
6594 * (that is, replaced by its individual array elements).
6595 * - Each element that is not an array is unchanged
6596 * (even if the element is an object that has instance method +flatten+).
6598 * Returns +nil+ if no elements were flattened.
6600 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6602 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6603 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6604 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6605 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6606 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6607 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6609 * With +nil+ or negative argument +depth+, flattens all levels:
6611 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6612 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6614 * Related: Array#flatten;
6615 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6619 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6621 int mod
= 0, level
= -1;
6624 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6625 rb_ary_modify_check(ary
);
6626 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6627 if (level
== 0) return Qnil
;
6629 result
= flatten(ary
, level
);
6630 if (result
== ary
) {
6633 if (!(mod
= ARY_EMBED_P(result
))) rb_ary_freeze(result
);
6634 rb_ary_replace(ary
, result
);
6635 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6642 * flatten(depth = nil) -> new_array
6644 * Returns a new array that is a recursive flattening of +self+
6645 * to +depth+ levels of recursion;
6646 * +depth+ must be an
6647 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6649 * At each level of recursion:
6651 * - Each element that is an array is "flattened"
6652 * (that is, replaced by its individual array elements).
6653 * - Each element that is not an array is unchanged
6654 * (even if the element is an object that has instance method +flatten+).
6656 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6658 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6659 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6660 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6661 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6662 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6663 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6664 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6666 * With +nil+ or negative +depth+, flattens all levels.
6668 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6669 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6671 * Related: Array#flatten!;
6672 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6676 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6681 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6682 level
= NUM2INT(argv
[0]);
6683 if (level
== 0) return ary_make_shared_copy(ary
);
6686 result
= flatten(ary
, level
);
6687 if (result
== ary
) {
6688 result
= ary_make_shared_copy(ary
);
6694 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6697 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6702 i
= len
= RARRAY_LEN(ary
);
6703 RARRAY_PTR_USE(ary
, ptr
, {
6705 long j
= RAND_UPTO(i
);
6707 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6708 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6714 }); /* WB: no new reference */
6719 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6721 ary
= rb_ary_dup(ary
);
6722 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6726 static const rb_data_type_t ary_sample_memo_type
= {
6727 .wrap_struct_name
= "ary_sample_memo",
6729 .dfree
= (RUBY_DATA_FUNC
)st_free_table
,
6731 .flags
= RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_FREE_IMMEDIATELY
6735 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6738 long n
, len
, i
, j
, k
, idx
[10];
6739 long rnds
[numberof(idx
)];
6740 long memo_threshold
;
6742 len
= RARRAY_LEN(ary
);
6749 return rb_ary_elt(ary
, i
);
6752 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6753 if (n
> len
) n
= len
;
6754 if (n
<= numberof(idx
)) {
6755 for (i
= 0; i
< n
; ++i
) {
6756 rnds
[i
] = RAND_UPTO(len
- i
);
6760 len
= RARRAY_LEN(ary
);
6761 if (len
< k
&& n
<= numberof(idx
)) {
6762 for (i
= 0; i
< n
; ++i
) {
6763 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6766 if (n
> len
) n
= len
;
6769 return rb_ary_new_capa(0);
6772 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6777 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6784 if (j
>= i
) l
= i
, g
= ++j
;
6785 if (k
>= l
&& (++k
>= g
)) ++k
;
6787 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6790 len
< 2560 ? len
/ 128 :
6791 len
< 5120 ? len
/ 64 :
6792 len
< 10240 ? len
/ 32 :
6794 if (n
<= numberof(idx
)) {
6795 long sorted
[numberof(idx
)];
6796 sorted
[0] = idx
[0] = rnds
[0];
6797 for (i
=1; i
<n
; i
++) {
6799 for (j
= 0; j
< i
; ++j
) {
6800 if (k
< sorted
[j
]) break;
6803 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6804 sorted
[j
] = idx
[i
] = k
;
6806 result
= rb_ary_new_capa(n
);
6807 RARRAY_PTR_USE(result
, ptr_result
, {
6808 for (i
=0; i
<n
; i
++) {
6809 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6813 else if (n
<= memo_threshold
/ 2) {
6815 VALUE vmemo
= TypedData_Wrap_Struct(0, &ary_sample_memo_type
, 0);
6816 st_table
*memo
= st_init_numtable_with_size(n
);
6817 RTYPEDDATA_DATA(vmemo
) = memo
;
6818 result
= rb_ary_new_capa(n
);
6819 RARRAY_PTR_USE(result
, ptr_result
, {
6820 for (i
=0; i
<n
; i
++) {
6821 long r
= RAND_UPTO(len
-i
) + i
;
6823 if (r
> max_idx
) max_idx
= r
;
6825 len
= RARRAY_LEN(ary
);
6826 if (len
<= max_idx
) n
= 0;
6827 else if (n
> len
) n
= len
;
6828 RARRAY_PTR_USE(ary
, ptr_ary
, {
6829 for (i
=0; i
<n
; i
++) {
6830 long j2
= j
= ptr_result
[i
];
6833 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6834 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6835 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6836 ptr_result
[i
] = ptr_ary
[j2
];
6840 RTYPEDDATA_DATA(vmemo
) = 0;
6841 st_free_table(memo
);
6845 result
= rb_ary_dup(ary
);
6846 RBASIC_CLEAR_CLASS(result
);
6848 RARRAY_PTR_USE(result
, ptr_result
, {
6849 for (i
=0; i
<n
; i
++) {
6850 j
= RAND_UPTO(len
-i
) + i
;
6852 ptr_result
[j
] = ptr_result
[i
];
6856 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6858 ARY_SET_LEN(result
, n
);
6864 ary_sized_alloc(rb_execution_context_t
*ec
, VALUE self
)
6866 return rb_ary_new2(RARRAY_LEN(self
));
6870 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6872 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6876 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6880 if (args
&& (RARRAY_LEN(args
) > 0)) {
6881 n
= RARRAY_AREF(args
, 0);
6883 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6884 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6886 if (mul
<= 0) return INT2FIX(0);
6888 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6893 * cycle(count = nil) {|element| ... } -> nil
6894 * cycle(count = nil) -> new_enumerator
6896 * With a block given, may call the block, depending on the value of argument +count+;
6897 * +count+ must be an
6898 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6901 * When +count+ is positive,
6902 * calls the block with each element, then does so repeatedly,
6903 * until it has done so +count+ times; returns +nil+:
6906 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6907 * output # => [0, 1, 0, 1]
6909 * When +count+ is zero or negative, does not call the block:
6911 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6912 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6914 * When +count+ is +nil+, cycles forever:
6916 * # Prints 0 and 1 forever.
6917 * [0, 1].cycle {|element| puts element }
6918 * [0, 1].cycle(nil) {|element| puts element }
6920 * With no block given, returns a new Enumerator.
6922 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6925 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6929 rb_check_arity(argc
, 0, 1);
6931 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6932 if (argc
== 0 || NIL_P(argv
[0])) {
6936 n
= NUM2LONG(argv
[0]);
6937 if (n
<= 0) return Qnil
;
6940 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6941 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6942 rb_yield(RARRAY_AREF(ary
, i
));
6949 * Build a ruby array of the corresponding values and yield it to the
6951 * Return the class of +values+ for reentry check.
6954 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6956 const VALUE result
= rb_ary_new2(r
);
6959 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6960 ARY_SET_LEN(result
, r
);
6962 return !RBASIC(values
)->klass
;
6966 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6968 * When we have a complete permutation of array indices, copy the values
6969 * at those indices into a new array and yield that array.
6971 * n: the size of the set
6972 * r: the number of elements in each permutation
6973 * p: the array (of size r) that we're filling in
6974 * used: an array of booleans: whether a given index is already used
6975 * values: the Ruby array that holds the actual values to permute
6978 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6980 long i
= 0, index
= 0;
6983 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6986 i
= p
[--index
]; /* pop index */
6987 used
[i
++] = 0; /* index unused */
6992 used
[i
] = 1; /* mark index used */
6994 if (index
< r
-1) { /* if not done yet */
6998 for (i
= 0; i
< n
; ++i
) {
6999 if (used
[i
]) continue;
7001 if (!yield_indexed_values(values
, r
, p
)) {
7002 rb_raise(rb_eRuntimeError
, "permute reentered");
7005 i
= p
[--index
]; /* pop index */
7006 used
[i
] = 0; /* index unused */
7013 * Returns the product of from, from-1, ..., from - how_many + 1.
7014 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7017 descending_factorial(long from
, long how_many
)
7021 cnt
= LONG2FIX(from
);
7022 while (--how_many
> 0) {
7024 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
7028 cnt
= LONG2FIX(how_many
== 0);
7034 binomial_coefficient(long comb
, long size
)
7038 if (comb
> size
-comb
) {
7044 else if (comb
== 0) {
7048 for (i
= 1; i
< comb
; ++i
) {
7049 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
7050 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
7056 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7058 long n
= RARRAY_LEN(ary
);
7059 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
7061 return descending_factorial(n
, k
);
7066 * permutation(count = self.size) {|permutation| ... } -> self
7067 * permutation(count = self.size) -> new_enumerator
7069 * Iterates over permutations of the elements of +self+;
7070 * the order of permutations is indeterminate.
7072 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7073 * calls the block with each permutation of +self+ of size +count+;
7078 * a.permutation(1) {|perm| perms.push(perm) }
7079 * perms # => [[0], [1], [2]]
7082 * a.permutation(2) {|perm| perms.push(perm) }
7083 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7086 * a.permutation(3) {|perm| perms.push(perm) }
7087 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7089 * When +count+ is zero, calls the block once with a new empty array:
7092 * a.permutation(0) {|perm| perms.push(perm) }
7095 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7096 * does not call the block:
7098 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7099 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7101 * With no block given, returns a new Enumerator.
7103 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7107 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
7111 n
= RARRAY_LEN(ary
); /* Array length */
7112 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
7114 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
7115 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
7117 if (r
< 0 || n
< r
) {
7118 /* no permutations: yield nothing */
7120 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7121 rb_yield(rb_ary_new2(0));
7123 else if (r
== 1) { /* this is a special, easy case */
7124 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7125 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7128 else { /* this is the general case */
7130 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
7131 char *used
= (char*)(p
+ r
);
7132 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7133 RBASIC_CLEAR_CLASS(ary0
);
7135 MEMZERO(used
, char, n
); /* initialize array */
7137 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
7139 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7145 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
7149 MEMZERO(stack
+1, long, n
);
7152 for (lev
++; lev
< n
; lev
++) {
7153 stack
[lev
+1] = stack
[lev
]+1;
7155 if (!yield_indexed_values(values
, n
, stack
+1)) {
7156 rb_raise(rb_eRuntimeError
, "combination reentered");
7159 if (lev
== 0) return;
7161 } while (stack
[lev
+1]+n
== len
+lev
+1);
7166 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7168 long n
= RARRAY_LEN(ary
);
7169 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7171 return binomial_coefficient(k
, n
);
7176 * combination(count) {|element| ... } -> self
7177 * combination(count) -> new_enumerator
7179 * When a block and a positive
7180 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7181 * argument +count+ (<tt>0 < count <= self.size</tt>)
7182 * are given, calls the block with each combination of +self+ of size +count+;
7185 * a = %w[a b c] # => ["a", "b", "c"]
7186 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7194 * The order of the yielded combinations is not guaranteed.
7196 * When +count+ is zero, calls the block once with a new empty array:
7198 * a.combination(0) {|combination| p combination }
7199 * [].combination(0) {|combination| p combination }
7206 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7207 * does not call the block:
7209 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7210 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7212 * With no block given, returns a new Enumerator.
7214 * Related: Array#permutation;
7215 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7219 rb_ary_combination(VALUE ary
, VALUE num
)
7224 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7225 len
= RARRAY_LEN(ary
);
7226 if (n
< 0 || len
< n
) {
7230 rb_yield(rb_ary_new2(0));
7233 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7234 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7238 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7240 long *stack
= ALLOCV_N(long, t0
, n
+1);
7242 RBASIC_CLEAR_CLASS(ary0
);
7243 combinate0(len
, n
, stack
, ary0
);
7245 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7251 * Compute repeated permutations of +r+ elements of the set
7252 * <code>[0..n-1]</code>.
7254 * When we have a complete repeated permutation of array indices, copy the
7255 * values at those indices into a new array and yield that array.
7257 * n: the size of the set
7258 * r: the number of elements in each permutation
7259 * p: the array (of size r) that we're filling in
7260 * values: the Ruby array that holds the actual values to permute
7263 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7265 long i
= 0, index
= 0;
7269 if (++index
< r
-1) {
7273 for (i
= 0; i
< n
; ++i
) {
7275 if (!yield_indexed_values(values
, r
, p
)) {
7276 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7280 if (index
<= 0) return;
7281 } while ((i
= ++p
[--index
]) >= n
);
7286 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7288 long n
= RARRAY_LEN(ary
);
7289 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7295 return LONG2FIX(!k
);
7297 return rb_int_positive_pow(n
, (unsigned long)k
);
7302 * repeated_permutation(size) {|permutation| ... } -> self
7303 * repeated_permutation(size) -> new_enumerator
7305 * With a block given, calls the block with each repeated permutation of length +size+
7306 * of the elements of +self+;
7307 * each permutation is an array;
7308 * returns +self+. The order of the permutations is indeterminate.
7310 * If a positive integer argument +size+ is given,
7311 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7312 * The number of permutations is <tt>self.size**size</tt>.
7319 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7320 * p # => [[0], [1], [2]]
7325 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7326 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7328 * If +size+ is zero, calls the block once with an empty array.
7330 * If +size+ is negative, does not call the block:
7332 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7334 * With no block given, returns a new Enumerator.
7336 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7339 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7343 n
= RARRAY_LEN(ary
); /* Array length */
7344 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7345 r
= NUM2LONG(num
); /* Permutation size from argument */
7348 /* no permutations: yield nothing */
7350 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7351 rb_yield(rb_ary_new2(0));
7353 else if (r
== 1) { /* this is a special, easy case */
7354 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7355 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7358 else { /* this is the general case */
7360 long *p
= ALLOCV_N(long, t0
, r
);
7361 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7362 RBASIC_CLEAR_CLASS(ary0
);
7364 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7366 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7372 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7374 long i
= 0, index
= 0;
7378 if (++index
< r
-1) {
7382 for (; i
< n
; ++i
) {
7384 if (!yield_indexed_values(values
, r
, p
)) {
7385 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7389 if (index
<= 0) return;
7390 } while ((i
= ++p
[--index
]) >= n
);
7395 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7397 long n
= RARRAY_LEN(ary
);
7398 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7402 return binomial_coefficient(k
, n
+ k
- 1);
7407 * repeated_combination(size) {|combination| ... } -> self
7408 * repeated_combination(size) -> new_enumerator
7410 * With a block given, calls the block with each repeated combination of length +size+
7411 * of the elements of +self+;
7412 * each combination is an array;
7413 * returns +self+. The order of the combinations is indeterminate.
7415 * If a positive integer argument +size+ is given,
7416 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7417 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7424 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7425 * c # => [[0], [1], [2]]
7430 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7431 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7433 * If +size+ is zero, calls the block once with an empty array.
7435 * If +size+ is negative, does not call the block:
7437 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7439 * With no block given, returns a new Enumerator.
7441 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7445 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7449 n
= NUM2LONG(num
); /* Combination size from argument */
7450 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7451 len
= RARRAY_LEN(ary
);
7456 rb_yield(rb_ary_new2(0));
7459 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7460 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7463 else if (len
== 0) {
7468 long *p
= ALLOCV_N(long, t0
, n
);
7469 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7470 RBASIC_CLEAR_CLASS(ary0
);
7472 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7474 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7481 * product(*other_arrays) -> new_array
7482 * product(*other_arrays) {|combination| ... } -> self
7484 * Computes all combinations of elements from all the arrays,
7485 * including both +self+ and +other_arrays+:
7487 * - The number of combinations is the product of the sizes of all the arrays,
7488 * including both +self+ and +other_arrays+.
7489 * - The order of the returned combinations is indeterminate.
7491 * With no block given, returns the combinations as an array of arrays:
7493 * p = [0, 1].product([2, 3])
7494 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7496 * p = [0, 1].product([2, 3], [4, 5])
7497 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7500 * If +self+ or any argument is empty, returns an empty array:
7502 * [].product([2, 3], [4, 5]) # => []
7503 * [0, 1].product([2, 3], []) # => []
7505 * If no argument is given, returns an array of 1-element arrays,
7506 * each containing an element of +self+:
7508 * a.product # => [[0], [1], [2]]
7510 * With a block given, calls the block with each combination; returns +self+:
7513 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7514 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7516 * If +self+ or any argument is empty, does not call the block:
7518 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7520 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7523 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7526 * [0, 1].product {|combination| p.push(combination) }
7529 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7533 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7535 int n
= argc
+1; /* How many arrays we're operating on */
7536 volatile VALUE t0
= rb_ary_hidden_new(n
);
7537 volatile VALUE t1
= Qundef
;
7538 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7539 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7540 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7544 RBASIC_CLEAR_CLASS(t0
);
7546 /* initialize the arrays of arrays */
7549 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7550 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7552 /* initialize the counters for the arrays */
7553 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7555 /* Otherwise, allocate and fill in an array of results */
7556 if (rb_block_given_p()) {
7557 /* Make defensive copies of arrays; exit if any is empty */
7558 for (i
= 0; i
< n
; i
++) {
7559 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7560 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7564 /* Compute the length of the result array; return [] if any is empty */
7565 for (i
= 0; i
< n
; i
++) {
7566 long k
= RARRAY_LEN(arrays
[i
]);
7568 result
= rb_ary_new2(0);
7571 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7572 rb_raise(rb_eRangeError
, "too big to product");
7575 result
= rb_ary_new2(resultlen
);
7579 /* fill in one subarray */
7580 VALUE subarray
= rb_ary_new2(n
);
7581 for (j
= 0; j
< n
; j
++) {
7582 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7585 /* put it on the result array */
7586 if (NIL_P(result
)) {
7587 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7589 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7590 rb_raise(rb_eRuntimeError
, "product reentered");
7593 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7597 rb_ary_push(result
, subarray
);
7601 * Increment the last counter. If it overflows, reset to 0
7602 * and increment the one before it.
7606 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7608 /* If the first counter overflows, we are done */
7609 if (--m
< 0) goto done
;
7617 return NIL_P(result
) ? ary
: result
;
7622 * take(count) -> new_array
7624 * Returns a new array containing the first +count+ element of +self+
7626 * +count+ must be a non-negative numeric;
7627 * does not modify +self+:
7629 * a = ['a', 'b', 'c', 'd']
7630 * a.take(2) # => ["a", "b"]
7631 * a.take(2.1) # => ["a", "b"]
7632 * a.take(50) # => ["a", "b", "c", "d"]
7635 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7639 rb_ary_take(VALUE obj
, VALUE n
)
7641 long len
= NUM2LONG(n
);
7643 rb_raise(rb_eArgError
, "attempt to take negative size");
7645 return rb_ary_subseq(obj
, 0, len
);
7650 * take_while {|element| ... } -> new_array
7651 * take_while -> new_enumerator
7653 * With a block given, calls the block with each successive element of +self+;
7654 * stops iterating if the block returns +false+ or +nil+;
7655 * returns a new array containing those elements for which the block returned a truthy value:
7657 * a = [0, 1, 2, 3, 4, 5]
7658 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7659 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7660 * a.take_while {|element| false } # => []
7662 * With no block given, returns a new Enumerator.
7664 * Does not modify +self+.
7666 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7670 rb_ary_take_while(VALUE ary
)
7674 RETURN_ENUMERATOR(ary
, 0, 0);
7675 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7676 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7678 return rb_ary_take(ary
, LONG2FIX(i
));
7683 * drop(count) -> new_array
7685 * Returns a new array containing all but the first +count+ element of +self+,
7686 * where +count+ is a non-negative integer;
7687 * does not modify +self+.
7691 * a = [0, 1, 2, 3, 4, 5]
7692 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7693 * a.drop(1) # => [1, 2, 3, 4, 5]
7694 * a.drop(2) # => [2, 3, 4, 5]
7697 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7701 rb_ary_drop(VALUE ary
, VALUE n
)
7704 long pos
= NUM2LONG(n
);
7706 rb_raise(rb_eArgError
, "attempt to drop negative size");
7709 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7710 if (NIL_P(result
)) result
= rb_ary_new();
7716 * drop_while {|element| ... } -> new_array
7717 * drop_while -> new_enumerator
7719 * With a block given, calls the block with each successive element of +self+;
7720 * stops if the block returns +false+ or +nil+;
7721 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7722 * does not modify +self+:
7724 * a = [0, 1, 2, 3, 4, 5]
7725 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7727 * With no block given, returns a new Enumerator.
7729 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7733 rb_ary_drop_while(VALUE ary
)
7737 RETURN_ENUMERATOR(ary
, 0, 0);
7738 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7739 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7741 return rb_ary_drop(ary
, LONG2FIX(i
));
7746 * any? -> true or false
7747 * any?(object) -> true or false
7748 * any? {|element| ... } -> true or false
7750 * Returns whether for any element of +self+, a given criterion is satisfied.
7752 * With no block and no argument, returns whether any element of +self+ is truthy:
7754 * [nil, false, []].any? # => true # Array object is truthy.
7755 * [nil, false, {}].any? # => true # Hash object is truthy.
7756 * [nil, false, ''].any? # => true # String object is truthy.
7757 * [nil, false].any? # => false # Nil and false are not truthy.
7759 * With argument +object+ given,
7760 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7762 * [nil, false, 0].any?(0) # => true
7763 * [nil, false, 1].any?(0) # => false
7764 * [nil, false, 'food'].any?(/foo/) # => true
7765 * [nil, false, 'food'].any?(/bar/) # => false
7767 * With a block given,
7768 * calls the block with each element in +self+;
7769 * returns whether the block returns any truthy value:
7771 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7772 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7774 * With both a block and argument +object+ given,
7775 * ignores the block and uses +object+ as above.
7777 * <b>Special case</b>: returns +false+ if +self+ is empty
7778 * (regardless of any given argument or block).
7780 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7784 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7786 long i
, len
= RARRAY_LEN(ary
);
7788 rb_check_arity(argc
, 0, 1);
7789 if (!len
) return Qfalse
;
7791 if (rb_block_given_p()) {
7792 rb_warn("given block not used");
7794 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7795 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7798 else if (!rb_block_given_p()) {
7799 for (i
= 0; i
< len
; ++i
) {
7800 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7804 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7805 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7813 * all? -> true or false
7814 * all?(object) -> true or false
7815 * all? {|element| ... } -> true or false
7817 * Returns whether for every element of +self+,
7818 * a given criterion is satisfied.
7820 * With no block and no argument,
7821 * returns whether every element of +self+ is truthy:
7823 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7824 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7825 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7827 * With argument +object+ given, returns whether <tt>object === ele</tt>
7828 * for every element +ele+ in +self+:
7830 * [0, 0, 0].all?(0) # => true
7831 * [0, 1, 2].all?(1) # => false
7832 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7833 * ['food', 'drink'].all?(/foo/) # => false
7835 * With a block given, calls the block with each element in +self+;
7836 * returns whether the block returns only truthy values:
7838 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7839 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7841 * With both a block and argument +object+ given,
7842 * ignores the block and uses +object+ as above.
7844 * <b>Special case</b>: returns +true+ if +self+ is empty
7845 * (regardless of any given argument or block).
7847 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7851 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7853 long i
, len
= RARRAY_LEN(ary
);
7855 rb_check_arity(argc
, 0, 1);
7856 if (!len
) return Qtrue
;
7858 if (rb_block_given_p()) {
7859 rb_warn("given block not used");
7861 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7862 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7865 else if (!rb_block_given_p()) {
7866 for (i
= 0; i
< len
; ++i
) {
7867 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7871 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7872 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7880 * none? -> true or false
7881 * none?(object) -> true or false
7882 * none? {|element| ... } -> true or false
7884 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7886 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7887 * +false+ otherwise:
7889 * [nil, false].none? # => true
7890 * [nil, 0, false].none? # => false
7891 * [].none? # => true
7893 * With argument +object+ given, returns +false+ if for any element +element+,
7894 * <tt>object === element</tt>; +true+ otherwise:
7896 * ['food', 'drink'].none?(/bar/) # => true
7897 * ['food', 'drink'].none?(/foo/) # => false
7898 * [].none?(/foo/) # => true
7899 * [0, 1, 2].none?(3) # => true
7900 * [0, 1, 2].none?(1) # => false
7902 * With a block given, calls the block with each element in +self+;
7903 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7905 * [0, 1, 2].none? {|element| element > 3 } # => true
7906 * [0, 1, 2].none? {|element| element > 1 } # => false
7908 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7912 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7914 long i
, len
= RARRAY_LEN(ary
);
7916 rb_check_arity(argc
, 0, 1);
7917 if (!len
) return Qtrue
;
7919 if (rb_block_given_p()) {
7920 rb_warn("given block not used");
7922 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7923 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7926 else if (!rb_block_given_p()) {
7927 for (i
= 0; i
< len
; ++i
) {
7928 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7932 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7933 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7941 * one? -> true or false
7942 * one? {|element| ... } -> true or false
7943 * one?(object) -> true or false
7945 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7947 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7948 * +false+ otherwise:
7950 * [nil, 0].one? # => true
7951 * [0, 0].one? # => false
7952 * [nil, nil].one? # => false
7953 * [].one? # => false
7955 * With a block given, calls the block with each element in +self+;
7956 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7958 * [0, 1, 2].one? {|element| element > 0 } # => false
7959 * [0, 1, 2].one? {|element| element > 1 } # => true
7960 * [0, 1, 2].one? {|element| element > 2 } # => false
7962 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7963 * +false+ otherwise:
7965 * [0, 1, 2].one?(0) # => true
7966 * [0, 0, 1].one?(0) # => false
7967 * [1, 1, 2].one?(0) # => false
7968 * ['food', 'drink'].one?(/bar/) # => false
7969 * ['food', 'drink'].one?(/foo/) # => true
7970 * [].one?(/foo/) # => false
7972 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7976 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7978 long i
, len
= RARRAY_LEN(ary
);
7979 VALUE result
= Qfalse
;
7981 rb_check_arity(argc
, 0, 1);
7982 if (!len
) return Qfalse
;
7984 if (rb_block_given_p()) {
7985 rb_warn("given block not used");
7987 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7988 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7989 if (result
) return Qfalse
;
7994 else if (!rb_block_given_p()) {
7995 for (i
= 0; i
< len
; ++i
) {
7996 if (RTEST(RARRAY_AREF(ary
, i
))) {
7997 if (result
) return Qfalse
;
8003 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
8004 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
8005 if (result
) return Qfalse
;
8015 * array.dig(index, *identifiers) -> object
8017 * Finds and returns the object in nested object
8018 * specified by +index+ and +identifiers+;
8019 * the nested objects may be instances of various classes.
8020 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8024 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8025 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8026 * a.dig(1, 2) # => [:bat, :bam]
8027 * a.dig(1, 2, 0) # => :bat
8028 * a.dig(1, 2, 3) # => nil
8030 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8034 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
8036 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
8037 self
= rb_ary_at(self
, *argv
);
8038 if (!--argc
) return self
;
8040 return rb_obj_dig(argc
, argv
, self
, Qnil
);
8044 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
8047 v
= rb_fix_plus(LONG2FIX(n
), v
);
8049 v
= rb_rational_plus(r
, v
);
8052 v
= rb_fix_plus(LONG2FIX(0), v
);
8059 * sum(init = 0) -> object
8060 * sum(init = 0) {|element| ... } -> object
8062 * With no block given, returns the sum of +init+ and all elements of +self+;
8063 * for array +array+ and value +init+, equivalent to:
8066 * array.each {|element| sum += element }
8069 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8073 * [0, 1, 2, 3].sum # => 6
8074 * [0, 1, 2, 3].sum(100) # => 106
8075 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8076 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8077 * # => [2, 3, :foo, :bar, "foo", "bar"]
8079 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8081 * # Raises TypeError: Array can't be coerced into Integer.
8082 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8084 * With a block given, calls the block with each element of +self+;
8085 * the block's return value (instead of the element itself) is used as the addend:
8087 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8088 * # => "Coerced and concatenated: zero1two"
8092 * - Array#join and Array#flatten may be faster than Array#sum
8093 * for an array of strings or an array of arrays.
8094 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8099 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
8105 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
8107 block_given
= rb_block_given_p();
8109 if (RARRAY_LEN(ary
) == 0)
8115 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
8117 goto init_is_a_value
;
8120 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
8121 e
= RARRAY_AREF(ary
, i
);
8125 n
+= FIX2LONG(e
); /* should not overflow long type */
8127 v
= rb_big_plus(LONG2NUM(n
), v
);
8131 else if (RB_BIGNUM_TYPE_P(e
))
8132 v
= rb_big_plus(e
, v
);
8133 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8137 r
= rb_rational_plus(r
, e
);
8142 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8146 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8148 if (RB_FLOAT_TYPE_P(e
)) {
8150 * Kahan-Babuska balancing compensated summation algorithm
8151 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8158 goto has_float_value
;
8159 for (; i
< RARRAY_LEN(ary
); i
++) {
8160 e
= RARRAY_AREF(ary
, i
);
8163 if (RB_FLOAT_TYPE_P(e
))
8165 x
= RFLOAT_VALUE(e
);
8166 else if (FIXNUM_P(e
))
8168 else if (RB_BIGNUM_TYPE_P(e
))
8170 else if (RB_TYPE_P(e
, T_RATIONAL
))
8175 if (isnan(f
)) continue;
8181 if (isinf(f
) && signbit(x
) != signbit(f
))
8187 if (isinf(f
)) continue;
8190 if (fabs(f
) >= fabs(x
))
8203 goto has_some_value
;
8205 for (; i
< RARRAY_LEN(ary
); i
++) {
8206 e
= RARRAY_AREF(ary
, i
);
8210 v
= rb_funcall(v
, idPLUS
, 1, e
);
8217 rb_ary_deconstruct(VALUE ary
)
8223 * An \Array object is an ordered, integer-indexed collection of objects,
8224 * called _elements_;
8225 * the object represents
8226 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8228 * An element may be any object (even another array);
8229 * elements may be any mixture of objects of different types.
8231 * Important data structures that use arrays include:
8233 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8234 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8235 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8236 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8237 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8238 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8239 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8241 * There are also array-like data structures:
8243 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8244 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8245 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8246 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8247 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8251 * \Array indexing starts at 0, as in C or Java.
8253 * A non-negative index is an offset from the first element:
8255 * - Index 0 indicates the first element.
8256 * - Index 1 indicates the second element.
8259 * A negative index is an offset, backwards, from the end of the array:
8261 * - Index -1 indicates the last element.
8262 * - Index -2 indicates the next-to-last element.
8266 * === In-Range and Out-of-Range Indexes
8268 * A non-negative index is <i>in range</i> if and only if it is smaller than
8269 * the size of the array. For a 3-element array:
8271 * - Indexes 0 through 2 are in range.
8272 * - Index 3 is out of range.
8274 * A negative index is <i>in range</i> if and only if its absolute value is
8275 * not larger than the size of the array. For a 3-element array:
8277 * - Indexes -1 through -3 are in range.
8278 * - Index -4 is out of range.
8280 * === Effective Index
8282 * Although the effective index into an array is always an integer,
8283 * some methods (both within class \Array and elsewhere)
8284 * accept one or more non-integer arguments that are
8285 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8287 * == Creating Arrays
8289 * You can create an \Array object explicitly with:
8291 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8293 * [1, 'one', :one, [2, 'two', :two]]
8295 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8297 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8298 * %w[1 % *] # => ["1", "%", "*"]
8300 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8302 * %i[foo bar baz] # => [:foo, :bar, :baz]
8303 * %i[1 % *] # => [:"1", :%, :*]
8305 * - \Method Kernel#Array:
8307 * Array(["a", "b"]) # => ["a", "b"]
8308 * Array(1..5) # => [1, 2, 3, 4, 5]
8309 * Array(key: :value) # => [[:key, :value]]
8310 * Array(nil) # => []
8312 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8314 * - \Method Array.new:
8317 * Array.new(3) # => [nil, nil, nil]
8318 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8319 * Array.new(3, true) # => [true, true, true]
8321 * Note that the last example above populates the array
8322 * with references to the same object.
8323 * This is recommended only in cases where that object is a natively immutable object
8324 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8326 * Another way to create an array with various objects, using a block;
8327 * this usage is safe for mutable objects such as hashes, strings or
8330 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8332 * Here is a way to create a multi-dimensional array:
8334 * Array.new(3) {Array.new(3)}
8335 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8337 * A number of Ruby methods, both in the core and in the standard library,
8338 * provide instance method +to_a+, which converts an object to an array.
8346 * - OptionParser#to_a
8351 * - Benchmark::Tms#to_a
8353 * - Enumerator::Lazy#to_a
8355 * - Gem::NameTuple#to_a
8356 * - Gem::Platform#to_a
8357 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8358 * - Gem::SourceList#to_a
8359 * - OpenSSL::X509::Extension#to_a
8360 * - OpenSSL::X509::Name#to_a
8362 * - Rinda::RingFinger#to_a
8363 * - Ripper::Lexer::Elem#to_a
8364 * - RubyVM::InstructionSequence#to_a
8369 * In addition to the methods it mixes in through the Enumerable module, the
8370 * +Array+ class has proprietary methods for accessing, searching and otherwise
8371 * manipulating arrays.
8373 * Some of the more common ones are illustrated below.
8375 * == Accessing Elements
8377 * Elements in an array can be retrieved using the Array#[] method. It can
8378 * take a single integer argument (a numeric index), a pair of arguments
8379 * (start and length) or a range. Negative indices start counting from the end,
8380 * with -1 being the last element.
8382 * arr = [1, 2, 3, 4, 5, 6]
8386 * arr[2, 3] #=> [3, 4, 5]
8387 * arr[1..4] #=> [2, 3, 4, 5]
8388 * arr[1..-3] #=> [2, 3, 4]
8390 * Another way to access a particular array element is by using the #at method
8394 * The #slice method works in an identical manner to Array#[].
8396 * To raise an error for indices outside of the array bounds or else to
8397 * provide a default value when that happens, you can use #fetch.
8399 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8400 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8401 * arr.fetch(100, "oops") #=> "oops"
8403 * The special methods #first and #last will return the first and last
8404 * elements of an array, respectively.
8409 * To return the first +n+ elements of an array, use #take
8411 * arr.take(3) #=> [1, 2, 3]
8413 * #drop does the opposite of #take, by returning the elements after +n+
8414 * elements have been dropped:
8416 * arr.drop(3) #=> [4, 5, 6]
8418 * == Obtaining Information about an +Array+
8420 * Arrays keep track of their own length at all times. To query an array
8421 * about the number of elements it contains, use #length, #count or #size.
8423 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8424 * browsers.length #=> 5
8425 * browsers.count #=> 5
8427 * To check whether an array contains any elements at all
8429 * browsers.empty? #=> false
8431 * To check whether a particular item is included in the array
8433 * browsers.include?('Konqueror') #=> false
8435 * == Adding Items to Arrays
8437 * Items can be added to the end of an array by using either #push or #<<
8439 * arr = [1, 2, 3, 4]
8440 * arr.push(5) #=> [1, 2, 3, 4, 5]
8441 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8443 * #unshift will add a new item to the beginning of an array.
8445 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8447 * With #insert you can add a new element to an array at any position.
8449 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8451 * Using the #insert method, you can also insert multiple values at once:
8453 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8454 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8456 * == Removing Items from an +Array+
8458 * The method #pop removes the last element in an array and returns it:
8460 * arr = [1, 2, 3, 4, 5, 6]
8462 * arr #=> [1, 2, 3, 4, 5]
8464 * To retrieve and at the same time remove the first item, use #shift:
8467 * arr #=> [2, 3, 4, 5]
8469 * To delete an element at a particular index:
8471 * arr.delete_at(2) #=> 4
8474 * To delete a particular element anywhere in an array, use #delete:
8476 * arr = [1, 2, 2, 3]
8477 * arr.delete(2) #=> 2
8480 * A useful method if you need to remove +nil+ values from an array is
8483 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8484 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8485 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8486 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8487 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8489 * Another common need is to remove duplicate elements from an array.
8491 * It has the non-destructive #uniq, and destructive method #uniq!
8493 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8494 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8496 * == Iterating over Arrays
8498 * Like all classes that include the Enumerable module, +Array+ has an each
8499 * method, which defines what elements should be iterated over and how. In
8500 * case of Array's #each, all elements in the +Array+ instance are yielded to
8501 * the supplied block in sequence.
8503 * Note that this operation leaves the array unchanged.
8505 * arr = [1, 2, 3, 4, 5]
8506 * arr.each {|a| print a -= 10, " "}
8507 * # prints: -9 -8 -7 -6 -5
8508 * #=> [1, 2, 3, 4, 5]
8510 * Another sometimes useful iterator is #reverse_each which will iterate over
8511 * the elements in the array in reverse order.
8513 * words = %w[first second third fourth fifth sixth]
8515 * words.reverse_each {|word| str += "#{word} "}
8516 * p str #=> "sixth fifth fourth third second first "
8518 * The #map method can be used to create a new array based on the original
8519 * array, but with the values modified by the supplied block:
8521 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8522 * arr #=> [1, 2, 3, 4, 5]
8523 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8524 * arr #=> [1, 4, 9, 16, 25]
8527 * == Selecting Items from an +Array+
8529 * Elements can be selected from an array according to criteria defined in a
8530 * block. The selection can happen in a destructive or a non-destructive
8531 * manner. While the destructive operations will modify the array they were
8532 * called on, the non-destructive methods usually return a new array with the
8533 * selected elements, but leave the original array unchanged.
8535 * === Non-destructive Selection
8537 * arr = [1, 2, 3, 4, 5, 6]
8538 * arr.select {|a| a > 3} #=> [4, 5, 6]
8539 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8540 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8541 * arr #=> [1, 2, 3, 4, 5, 6]
8543 * === Destructive Selection
8545 * #select! and #reject! are the corresponding destructive methods to #select
8548 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8549 * opposite result when supplied with the same block:
8551 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8554 * arr = [1, 2, 3, 4, 5, 6]
8555 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8560 * First, what's elsewhere. \Class +Array+:
8562 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8563 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8564 * which provides dozens of additional methods.
8566 * Here, class +Array+ provides methods that are useful for:
8568 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8569 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8570 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8571 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8572 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8573 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8574 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8575 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8576 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8577 * - {And more....}[rdoc-ref:Array@Other+Methods]
8579 * === Methods for Creating an +Array+
8581 * - ::[]: Returns a new array populated with given objects.
8582 * - ::new: Returns a new array.
8583 * - ::try_convert: Returns a new array created from a given object.
8585 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8587 * === Methods for Querying
8589 * - #all?: Returns whether all elements meet a given criterion.
8590 * - #any?: Returns whether any element meets a given criterion.
8591 * - #count: Returns the count of elements that meet a given criterion.
8592 * - #empty?: Returns whether there are no elements.
8593 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8594 * - #hash: Returns the integer hash code.
8595 * - #include?: Returns whether any element <tt>==</tt> a given object.
8596 * - #length (aliased as #size): Returns the count of elements.
8597 * - #none?: Returns whether no element <tt>==</tt> a given object.
8598 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8599 * - #rindex: Returns the index of the last element that meets a given criterion.
8601 * === Methods for Comparing
8603 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8604 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8605 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8607 * === Methods for Fetching
8609 * These methods do not modify +self+.
8611 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8612 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8613 * - #at: Returns the element at a given offset.
8614 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8615 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8616 * - #compact: Returns an array containing all non-+nil+ elements.
8617 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8618 * - #drop: Returns trailing elements as determined by a given index.
8619 * - #drop_while: Returns trailing elements as determined by a given block.
8620 * - #fetch: Returns the element at a given offset.
8621 * - #fetch_values: Returns elements at given offsets.
8622 * - #first: Returns one or more leading elements.
8623 * - #last: Returns one or more trailing elements.
8624 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8625 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8626 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8627 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8628 * - #reject: Returns an array containing elements not rejected by a given block.
8629 * - #reverse: Returns all elements in reverse order.
8630 * - #rotate: Returns all elements with some rotated from one end to the other.
8631 * - #sample: Returns one or more random elements.
8632 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8633 * - #shuffle: Returns elements in a random order.
8634 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8635 * - #take: Returns leading elements as determined by a given index.
8636 * - #take_while: Returns leading elements as determined by a given block.
8637 * - #uniq: Returns an array containing non-duplicate elements.
8638 * - #values_at: Returns the elements at given offsets.
8640 * === Methods for Assigning
8642 * These methods add, replace, or reorder elements in +self+.
8644 * - #<<: Appends an element.
8645 * - #[]=: Assigns specified elements with a given object.
8646 * - #concat: Appends all elements from given arrays.
8647 * - #fill: Replaces specified elements with specified objects.
8648 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8649 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8650 * - #insert: Inserts given objects at a given offset; does not replace elements.
8651 * - #push (aliased as #append): Appends elements.
8652 * - #reverse!: Replaces +self+ with its elements reversed.
8653 * - #rotate!: Replaces +self+ with its elements rotated.
8654 * - #shuffle!: Replaces +self+ with its elements in random order.
8655 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8656 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8657 * - #unshift (aliased as #prepend): Prepends leading elements.
8659 * === Methods for Deleting
8661 * Each of these methods removes elements from +self+:
8663 * - #clear: Removes all elements.
8664 * - #compact!: Removes all +nil+ elements.
8665 * - #delete: Removes elements equal to a given object.
8666 * - #delete_at: Removes the element at a given offset.
8667 * - #delete_if: Removes elements specified by a given block.
8668 * - #keep_if: Removes elements not specified by a given block.
8669 * - #pop: Removes and returns the last element.
8670 * - #reject!: Removes elements specified by a given block.
8671 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8672 * - #shift: Removes and returns the first element.
8673 * - #slice!: Removes and returns a sequence of elements.
8674 * - #uniq!: Removes duplicates.
8676 * === Methods for Combining
8678 * - #&: Returns an array containing elements found both in +self+ and a given array.
8679 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8680 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8681 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8682 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8683 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8684 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8685 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8686 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8688 * === Methods for Iterating
8690 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8691 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8692 * - #each: Passes each element to a given block.
8693 * - #each_index: Passes each element index to a given block.
8694 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8695 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8696 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8697 * - #reverse_each: Passes each element, in reverse order, to a given block.
8699 * === Methods for Converting
8701 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8702 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8703 * - #flatten: Returns an array that is a recursive flattening of +self+.
8704 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8705 * - #join: Returns a newsString containing the elements joined by the field separator.
8706 * - #to_a: Returns +self+ or a new array containing all elements.
8707 * - #to_ary: Returns +self+.
8708 * - #to_h: Returns a new hash formed from the elements.
8709 * - #transpose: Transposes +self+, which must be an array of arrays.
8710 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8714 * - #*: Returns one of the following:
8716 * - With integer argument +n+, a new array that is the concatenation
8717 * of +n+ copies of +self+.
8718 * - With string argument +field_separator+, a new string that is equivalent to
8719 * <tt>join(field_separator)</tt>.
8721 * - #pack: Packs the elements into a binary sequence.
8722 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8728 fake_ary_flags
= init_fake_ary_flags();
8730 rb_cArray
= rb_define_class("Array", rb_cObject
);
8731 rb_include_module(rb_cArray
, rb_mEnumerable
);
8733 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8734 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8735 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8736 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8737 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8738 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8740 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8741 rb_define_alias(rb_cArray
, "to_s", "inspect");
8742 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8743 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8744 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8746 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8747 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8748 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8750 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8751 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8752 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8753 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8754 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8755 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8756 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8757 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8758 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8759 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8760 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8761 rb_define_alias(rb_cArray
, "append", "push");
8762 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8763 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8764 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8765 rb_define_alias(rb_cArray
, "prepend", "unshift");
8766 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8767 rb_define_method(rb_cArray
, "each", rb_ary_each
, 0);
8768 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8769 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8770 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8771 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8772 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8773 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8774 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8775 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8776 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8777 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8778 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8779 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8780 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8781 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8782 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8783 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8784 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8785 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8786 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8787 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8788 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8789 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8790 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8791 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8792 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8793 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8794 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8795 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8796 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8797 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8798 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8799 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8800 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8801 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8802 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8803 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8804 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8805 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8807 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8808 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8810 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8811 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8813 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8814 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8816 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8817 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8818 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8820 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8821 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8822 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8824 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8825 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8826 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8827 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8828 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8829 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8830 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8831 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8832 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8833 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8834 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8835 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8836 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8838 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8839 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8840 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8841 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8842 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8843 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8844 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8845 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8846 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8847 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8848 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8849 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8850 rb_define_method(rb_cArray
, "freeze", rb_ary_freeze
, 0);
8852 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8854 rb_cArray_empty_frozen
= rb_ary_freeze(rb_ary_new());
8855 rb_vm_register_global_object(rb_cArray_empty_frozen
);
8858 #include "array.rbinc"