# Range patch

**URL:** <https://www.ruby-forum.com/t/range-patch/127153>\
**Category:** IronRuby\
**Created:** [January 25, 2008, 3:57pm UTC](https://www.ruby-forum.com/t/range-patch/127153 "2008-01-25T15:57:48Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![editkid](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/977dab/32.png) [@editkid](https://www.ruby-forum.com/u/editkid)\
**Post date:** [January 25, 2008, 3:57pm UTC](https://www.ruby-forum.com/t/range-patch/127153/1 "2008-01-25T15:57:48Z")

</div>

Sorry, I introduced a small bug since I didn’t check all the other specs  
were still working (tut tut). The String#upto spec picked up a quirk of  
MRI  
that I broke in rbx:

# This is weird but MRI behaves like that

it “upto calls block with self even if self is less than stop but stop  
length is less than self length” do

```
a = []

"25".upto("5") { |s| a << s }

a.should == ["25"]

```

end

it “upto doesn’t call block if stop is less than self and stop length  
is  
less than self length” do

```
a = []

"25".upto("1") { |s| a << s }

a.should == []

```

end

This behaviour is also true for Range#each and Range#step too. The fix  
is  
as follows. If it is a problem I can resubmit the whole patch with this  
fix  
incorporated.

Inside the RangeOps.cs file, get rid of the CompareString method and  
change  
StepString to:

```
    private static Range StepString(CodeContext/*!*/ context, 

```

Range/_!_/  
self, BlockParam block, MutableString begin, MutableString end, int  
step) {

```
        CheckStep(step);

        MutableString item = begin;

        int comp;

        while((comp = Protocols.Compare(context, item, end)) < 0) {

            if (block.BlockJumped(_BlockSite.Invoke(context, block,

```

item))) {

```
                return self;

            }

            for (int i = 0; i < step; ++i) {

                item = (MutableString)RubySites.Successor(context,

```

item);

```
            }

            if (item.Length > end.Length) {

                return self;

            }

        }

        if (comp == 0 && !self.ExcludeEnd) {

            _BlockSite.Invoke(context, block, item);

        }

        return self;

    }
```

---

<div class="post-metadata">

**Author:** ![editkid](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/977dab/32.png) [@editkid](https://www.ruby-forum.com/u/editkid)\
**Post date:** [January 25, 2008, 4:17pm UTC](https://www.ruby-forum.com/t/range-patch/127153/2 "2008-01-25T16:17:12Z")

</div>

Thanks for the catch. Will review and submit ASAP.

Thanks!  
-John

From: removed\_email\_address@domain.invalid  
[[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)] On Behalf Of Peter Bacon  
Darwin  
Sent: Friday, January 25, 2008 6:53 AM  
To: removed\_email\_address@domain.invalid  
Subject: [Ironruby-core] Range patch

Sorry, I introduced a small bug since I didn’t check all the other specs  
were still working (tut tut). The String#upto spec picked up a quirk of  
MRI that I broke in rbx:

# This is weird but MRI behaves like that

it “upto calls block with self even if self is less than stop but stop  
length is less than self length” do  
a = []  
“25”.upto(“5”) { |s| a \<\< s }  
a.should == [“25”]  
end

it “upto doesn’t call block if stop is less than self and stop length  
is less than self length” do  
a = []  
“25”.upto(“1”) { |s| a \<\< s }  
a.should == []  
end

This behaviour is also true for Range#each and Range#step too. The fix  
is as follows. If it is a problem I can resubmit the whole patch with  
this fix incorporated.

Inside the RangeOps.cs file, get rid of the CompareString method and  
change StepString to:

```
    private static Range StepString(CodeContext/*!*/ context, 

```

Range/_!_/ self, BlockParam block, MutableString begin, MutableString  
end, int step) {  
CheckStep(step);  
MutableString item = begin;  
int comp;  
while((comp = Protocols.Compare(context, item, end)) \< 0) {  
if (block.BlockJumped(\_BlockSite.Invoke(context, block,  
item))) {  
return self;  
}  
for (int i = 0; i \< step; ++i) {  
item = (MutableString)RubySites.Successor(context,  
item);  
}  
if (item.Length \> end.Length) {  
return self;  
}  
}  
if (comp == 0 && !self.ExcludeEnd) {  
\_BlockSite.Invoke(context, block, item);  
}  
return self;  
}
