Proposal: Array#walker

View: New views
2 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

Re: Array#split_at

by Nobuyoshi Nakada-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

At Fri, 16 Nov 2007 18:47:50 +0900,
murphy wrote in [ruby-core:13597]:
> +VALUE
> +rb_ary_split_at(int argc, VALUE *argv, VALUE ary)
> +{
> +    return Qnil;

What's this?

> +    long pos, len;
> +    len = 1;  /* default */

> +    VALUE left  = ary_shared_array(rb_cArray, ary);
> +    VALUE right = ary_shared_array(rb_cArray, ary);

These need C99.

> +    RARRAY(left)->len = pos;
> +    RARRAY(right)->ptr += pos + len;
> +    RARRAY(right)->len += RARRAY_LEN(ary) - (pos + len);

The last assignment shouldn't be:
+    RARRAY(right)->len -= pos + len;
or
+    RARRAY(right)->len = RARRAY_LEN(ary) - (pos + len);
?

--
Nobu Nakada


Re: Array#split_at

by Kornelius Kalnbach :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Nobuyoshi Nakada wrote:
> At Fri, 16 Nov 2007 18:47:50 +0900,
> murphy wrote in [ruby-core:13597]:
>> +VALUE
>> +rb_ary_split_at(int argc, VALUE *argv, VALUE ary)
>> +{
>> +    return Qnil;
>
> What's this?
debugging artifacts, makes me look stupid. I misinterpreted the output
of "make test". sorry.

>> +    long pos, len;
>> +    len = 1;  /* default */
>
>> +    VALUE left  = ary_shared_array(rb_cArray, ary);
>> +    VALUE right = ary_shared_array(rb_cArray, ary);
>
> These need C99.
you mean, declare them at the top of the function? okay.

>
>> +    RARRAY(left)->len = pos;
>> +    RARRAY(right)->ptr += pos + len;
>> +    RARRAY(right)->len += RARRAY_LEN(ary) - (pos + len);
>
> The last assignment shouldn't be:
> +    RARRAY(right)->len -= pos + len;
> or
> +    RARRAY(right)->len = RARRAY_LEN(ary) - (pos + len);
> ?
>
I found another bug and rewrote this section. thank you.

the tests should now run for real.
[murphy]

Index: array.c
===================================================================
--- array.c (revision 13948)
+++ array.c (working copy)
@@ -781,6 +781,75 @@
     return rb_ary_entry(ary, NUM2LONG(pos));
 }
 
+/*
+ *  call-seq:
+ *     array.split_at(index)          -> [left_array, right_array]
+ *     array.split_at(start, length)  -> [left_array, right_array]
+ *
+ *  Splits an array into two parts, with the first one containing
+ *  all elements before the given range, and the second one containing
+ *  all elements after it.
+ *
+ *     a = [ "a", "b", "c", "d", "e" ]
+ *     a.split_at(0)          #=> [[], ["b", "c", "d", "e"]]
+ *     a.split_at(2)          #=> [["a", "b"], ["d", "e"]]
+ *     a.split_at(-1)         #=> [["a", "b", "c", "d"], []]
+ *     a.split_at(1, 2)       #=> [["a"], ["d", "e"]]
+ *     a.split_at(1, 0)       #=> [["a"], ["b", "c", "d", "e"]]
+ *  
+ */
+
+VALUE
+rb_ary_split_at(int argc, VALUE *argv, VALUE ary)
+{
+    long pos, len;
+    VALUE left, right;
+    len = 1;  /* default */
+    
+    switch (argc) {
+      case 2:
+ len = NUM2LONG(argv[1]);
+ /* fall through */
+      case 1:
+ pos = NUM2LONG(argv[0]);
+ break;
+      default:
+ rb_scan_args(argc, argv, "11", 0, 0);
+    }
+    
+    if (RARRAY_LEN(ary) == 0) {
+ return rb_assoc_new(rb_ary_new2(0), rb_ary_new2(0));
+    }
+    
+    if (pos < 0) {
+ pos += RARRAY_LEN(ary);
+    }
+    
+    /* pos out of bounds? */
+    if (pos < 0) {
+ return rb_assoc_new(rb_ary_new2(0), ary_shared_array(rb_cArray, ary));
+    }
+    
+    /* Array#slice doesn't fail on negative lengths, so we copy */
+    if (len < 0) {
+ len = 0;
+    }
+    
+    left  = ary_shared_array(rb_cArray, ary);
+    RARRAY(left)->len = pos;
+    
+    /* pos+len out of bounds? */
+    if (pos + len > RARRAY_LEN(ary)) {
+ return rb_assoc_new(left, rb_ary_new2(0));
+    }
+    
+    right = ary_shared_array(rb_cArray, ary);
+    RARRAY(right)->ptr += pos + len;
+    RARRAY(right)->len -= pos + len;
+    
+    return rb_assoc_new(left, right);
+}
+
 /*
  *  call-seq:
  *     array.first     ->   obj or nil
@@ -2557,7 +2626,7 @@
     hash = ary_make_hash(ary2, 0);
 
     if (RHASH_EMPTY_P(hash))
-        return ary3;
+ return ary3;
 
     for (i=0; i<RARRAY_LEN(ary1); i++) {
  v = vv = rb_ary_elt(ary1, i);
@@ -3288,6 +3357,7 @@
 
     rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
     rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
+    rb_define_method(rb_cArray, "split_at", rb_ary_split_at, -1);
 
     rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
     rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
< Prev | 1 - 2 | Next >