Forums

Equivalent to Python's range

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

Equivalent to Python's range

Postby neuruss » Wed Feb 13, 2008 6:02 pm

Is there any equivalent to range or xrange in Cobra?
If not, how would you write this in Cobra (or any other .NET language)?

mylist = range(10, 50)

(Sorry, I'm not expert in .Net...)

neuruss
neuruss
 
Posts: 23

Re: Equivalent to Python's range

Postby khjklujn » Wed Feb 13, 2008 9:19 pm

I can't say this is the proper .Net way of doing it, but it'll get the job done.

Code: Select all
class Range
   inherits List<of int>

   def init(beginning as int, ending as int)
      for i = beginning .. ending
         .add(i)
   
   def init(beginning as int, ending as int, stepBy as int)
      if beginning < ending and stepBy > 0
         for i = beginning .. ending ++stepBy
            .add(i)
      else if ending < beginning and stepBy < 0
         for i = beginning .. ending --(-stepBy)
            .add(i)

class Program
   def main is shared
      myList = Range(10, 50)
khjklujn
 
Posts: 29

Re: Equivalent to Python's range

Postby neuruss » Wed Feb 13, 2008 9:33 pm

It looks pretty good.
That would be a handy addition to the language. Or at least to my "useful"stuff library...

Thanks again!
neuruss
neuruss
 
Posts: 23

Re: Equivalent to Python's range

Postby khjklujn » Thu Feb 14, 2008 9:08 am

Some more robust examples of range and xrange.

class Range
inherits List<of int>
"""
Range emulates the behavior of Python's builtin range function. The behavior
differs in the case where the end value is less than the begin value or the
step value is in a nonsensical direction. In Python these cases return an
empty list. Here they will raise an exception.
"""

def init(beginning as int, ending as int, stepBy as int)
require
(beginning <= ending and stepBy > 0) or (ending <= beginning and stepBy < 0)

test
assert Range(0, 0, 1) == []
assert Range(0, 0, -1) == []
assert Range(0, 10, 2) == [0, 2, 4, 6, 8]
assert Range(10, 0, -2) == [10, 8, 6, 4, 2]

try
for i in Range(10, 0, 2)
assert false
catch Cobra.Lang.RequireException
assert true

try
for i in Range(0, 10, -2)
assert false
catch Cobra.Lang.RequireException
assert true

try
for i in Range(0, 10, 0)
assert false
catch Cobra.Lang.RequireException
assert true

body
if stepBy > 0
for i = beginning .. ending ++ stepBy
.add(i)
else
for i = beginning .. ending -- -stepBy
.add(i)

def init(beginning as int, ending as int)
.init(beginning, ending, 1)

class XRange
implements IEnumerable
"""
XRange emulates the behavior of Python's builtin xrange function. The behavior
differs in the case where the end value is less than the begin value or the
step value is in a nonsensical direction. In Python these cases return an
empty generator. Here they will raise an exception.
"""

var _beginning as int
var _ending as int
var _stepBy as int

def init(beginning as int, ending as int, stepBy as int)
require
(beginning <= ending and stepBy > 0) or (ending <= beginning and stepBy < 0)

test
for i in XRange(0, 0, 1)
assert false

for i in XRange(0, 0, -1)
assert false

c = 0
for i in XRange(0, 10, 2)
assert i == c
c += 2

c = 10
for i in XRange(10, 0, -2)
assert i == c
c -= 2

try
for i in XRange(10, 0, 2)
assert false
catch Cobra.Lang.RequireException
assert true

try
for i in XRange(0, 10, -2)
assert false
catch Cobra.Lang.RequireException
assert true

try
for i in XRange(0, 10, 0)
assert false
catch Cobra.Lang.RequireException
assert true

body
_beginning = beginning
_ending = ending
_stepBy = stepBy

def init(beginning as int, ending as int)
.init(beginning, ending, 1)

def getEnumerator as IEnumerator
if _stepBy > 0
for i = _beginning .. _ending ++ _stepBy
yield i
else
for i = _beginning .. _ending -- -_stepBy
yield i
khjklujn
 
Posts: 29

Re: Equivalent to Python's range

Postby khjklujn » Thu Feb 14, 2008 10:47 am

Addendum: the exception testing in the above example was incomplete--forgot to test the test. A better pattern would be something like:
# raise the exception
try
for i in Range(10, 0, 2)
assert false

# test the exception
catch Cobra.Lang.RequireException
assert true

# guarantee the exception was raised
# because the test may be flawed
success
assert false
khjklujn
 
Posts: 29

Re: Equivalent to Python's range

Postby Charles » Thu Feb 14, 2008 12:41 pm

There is an explicit statement for testing that an expected exception gets thrown:
expect RequireException
obj.foo

This will raise an ExpectException if the code does not raise precisely the exception expected. It also comes with a nice message telling you what exception was expected and whether there was no exception or the different type of exception that was raised instead.

You can have more than one statement in the block if you desire, although just having one is pretty common.

You can use "expect" in both "test" sections and regular code.
Charles
 
Posts: 2510
Location: Los Angeles, CA

Re: Equivalent to Python's range

Postby Charles » Thu Feb 14, 2008 1:02 pm

Btw I think I read that Python's range() was going to change to the xrange() behavior at some point. I recommend renaming your XRange class and giving it a .toList method:
def toList as List<of int>
return List<of int>(this)

Most of the time people won't care if Range is IEnumerable, but then if they really need that list they can tack on ".toList".
Charles
 
Posts: 2510
Location: Los Angeles, CA

Re: Equivalent to Python's range

Postby khjklujn » Thu Feb 14, 2008 3:18 pm

Chuck wrote:There is an explicit statement for testing that an expected exception gets thrown

Way cool.
Chuck wrote:I recommend renaming your XRange class and giving it a .toList method

Yeah, that would be more concise.
khjklujn
 
Posts: 29

Re: Equivalent to Python's range

Postby dennis » Thu Feb 14, 2008 6:40 pm

Why do you do:

if stepBy > 0
for i = beginning .. ending ++ stepBy
.add(i)
else
for i = beginning .. ending -- -stepBy
.add(i)


isn't incrementing by a negative the same as decrementing by a negated negative? Why couldn't it simply be:

for i = beginning .. ending ++ stepBy
.add(i)


without the if/else and duplicated for?

So I wrote a little program to test it and
for i = big .. small ++ neg
exits without executing the contents of the loop.
for i = big .. small -- -neg
works as expected, but I insist I don't have to like it. ;)
dennis
 
Posts: 21

Re: Equivalent to Python's range

Postby khjklujn » Thu Feb 14, 2008 10:07 pm

The compiler is using the ++ and -- to indicate which way the comparison is made in the exit condition of the loop.

No problem if you use them in a manner that makes sense to people who are used to working with C style languages (where ++i unequivocally means the loop index is gonna go up, --i always means down).

for i = 0 .. 10 ++ 2 ==> for(int i = 0; i < 10; i += 2) ==> works as expected
for i = 10 .. 0 -- 2 ==> for(int i = 10; i > 0; i -= 2) ==> works as expected

Syntactically, this one also makes sense, but...

for i = 10 .. 0 ++ -2 ==> for(int i = 10; i < 0; i += (-2)) ==> exits immediately

The problem is that in order to use the C# for loop, the direction of the comparison has to be determined at compile time, so you have to provide something to indicate which direction you think the index is supposed to go. The compiler can't use the values of the end points because they usually won't be known until runtime.

I suppose it might be possible to use something like that XRange class (renamed to Range, of course) to have the compiler generate:

for i = 10 .. 0 step -2 ==> foreach(int i in Range(10, 0, -2))

But that's Chuck's domain. There might be nontrivial performance differences between C#'s for and foreach that justify a syntax that doesn't appear to always make sense mathematically.

The syntax of C style for loops has always struck me as a little quirky. If you thought "exits immediately" was fun, give this one a try:

for i = 10 .. 0 ---2

I've had to hit Ctrl-C often enough to know that I don't always see the problem with that construct the first time I look at it.
khjklujn
 
Posts: 29

Next

Return to Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron