Let's create us some Dart ranges

167 views
Skip to first unread message

Olov Lassus

unread,
Nov 21, 2011, 5:42:32 AM11/21/11
to mi...@dartlang.org
Ranges has been mentioned on misc before but I figured that it would
be a nice example to write about anyways. Turns out that they are
actually quite convenient for things such as populating collections
with data. In a nutshell Range implements Collection, includes both
endpoints (i.e. it's closed), has a step defaulting to 1 and
convenience-functions range and indices. Write-up on
<http://blog.lassus.se/2011/11/lets-create-us-some-dart-ranges.html>,
source code on <https://github.com/olov/dart-range>. Feel free to
share,

/Olov

Peter Ahé

unread,
Nov 21, 2011, 8:15:45 AM11/21/11
to Olov Lassus, mi...@dartlang.org
Hi Olov,

What is your thinking behind including the endpoint?

Cheers,
Peter

Olov Lassus

unread,
Nov 21, 2011, 9:11:29 AM11/21/11
to Peter Ahé, mi...@dartlang.org
On Mon, Nov 21, 2011 at 2:15 PM, Peter Ahé <a...@google.com> wrote:
> What is your thinking behind including the endpoint?

Good question. My first implementation didn't do that actually, but
followed the Pythonic xrange style of excluding the stop endpoint. In
Python, this is nice for a number of reasons such as being consistent
with slices and supporting the for i in xrange(len(c)) pattern. [The
latter has been superseded by for i, v in enumerate(c) to some
extent.]

Things changed when I wrote the tests. When a Range is used to
actually generate ranges of discrete values, I found the closed
notation much easier (i.e. including both endpoints). Especially so
when supporting negative ranges and steps other than 1. So I changed
it.

On the other hand, when a Range is used to represent indices of a
sequence, be it for iterating over everything or for representing a
slice, then I think half-open makes more sense (excluding stop
endpoint). For now i just put in the indices function to handle the
simplest use-case as some kind of compromise.

Since Range isn't in corelibs I opted for the first use-case, but I
don't have a strong preference. If we would like to push Range (or
something Range'ish) further down then I think half-open is the way to
go for the Pythonic reasons.

/Olov

Jan

unread,
Nov 21, 2011, 10:12:46 AM11/21/11
to mi...@dartlang.org
It would be nice to have some kind of yield operator like in C#. So you could write generators like so:

for (i in take(5, squares())) {
  print(i); // 0, 1, 4, 9, 16
}

Iterable<int> squares() {
  int i = 0;
  while(true) {
    yield return i * i;
    i = i + 1;
  }
}

Iterable<int> take(n, generator) {
  var it = generator.iterator();
  for (i = 0; i < n; i++) {
    yield return it.next();
  }
}

One advantage of this approach is the deferred execution of the iterator logic. No square is calculated when you call squares(). Only when the next element is requested. I think this could also be used to create some nice range generators.

Olov Lassus

unread,
Nov 21, 2011, 10:37:12 AM11/21/11
to mi...@dartlang.org
On Mon, Nov 21, 2011 at 4:12 PM, Jan <potom...@gmail.com> wrote:
> It would be nice to have some kind of yield operator like in C#. So you
> could write generators like so:
> ...

> One advantage of this approach is the deferred execution of the iterator
> logic. No square is calculated when you call squares(). Only when the next
> element is requested. I think this could also be used to create some nice
> range generators.

I agree that Python/C#-style yield is nice, convenient and makes it
easier to create SICP-like lazy streams, but it's not of particular
use for Range. One could play with the thought of making Range.filter
or Range.map lazy instead of returning Lists, but it's not very useful
given the definition of Range; a sequence parametrized by start, stop
and step. Also do note that you can implement lazy collections today
already, it's just that you need to explicitly perform the same state
bookkeeping that yield would do for you.

Having said all that, I'd +1 a proposal of landing something yield'ish
in Dart before you finished saying "await!",

/Olov

Alan Knight

unread,
Nov 21, 2011, 5:13:30 PM11/21/11
to mi...@dartlang.org
So what's the advantage of this over just doing it with a closure.

Iterable<int> squares() {
int i = 0;

return IterableThing(()=>i*i++);
}

You need to have an Iterable object that knows to apply the closure, but
that seems pretty light compared to special syntax.

Jan

unread,
Nov 21, 2011, 5:32:11 PM11/21/11
to mi...@dartlang.org, kni...@acm.org
> So what's the advantage of this over just doing it with a closure.

Maybe not the squares but there are other possibilities

Iterable<int> doStuff() {
  yield return 1;
  yield return 2;
  yield return [3, 4, 5];
  yield return 6;
  yield return doStuff();
}

But that's really offtopic.

Ray Tayek

unread,
Jan 14, 2012, 11:53:55 AM1/14/12
to General Dart Discussion


On Nov 21 2011, 2:42 am, Olov Lassus <olov.las...@gmail.com> wrote:
> Ranges has been mentioned on misc before but I figured that it would
> be a nice example to write about anyways. ...

could range be a list of ranges? one might like to add and subtract
them.

or perhaps the for loop could take more than one range?

thanks

Olov Lassus

unread,
Jan 15, 2012, 1:26:24 PM1/15/12
to Ray Tayek, General Dart Discussion
On Sat, Jan 14, 2012 at 5:53 PM, Ray Tayek <rta...@ca.rr.com> wrote:
> could range be a list of ranges? one might like to add and subtract
> them.

Not in my example implementation but you should be able to create your
own DisjointRange based on it without a whole lot of new code.

/Olov

Ray Tayek

unread,
Jan 17, 2012, 3:23:11 PM1/17/12
to General Dart Discussion
At 08:53 AM 1/14/2012, Ray Tayek wrote:
>On Nov 21 2011, 2:42 am, Olov Lassus <olov.las...@gmail.com> wrote:
> > Ranges has been mentioned on misc before but I figured that it would
> > be a nice example to write about anyways. ...

groovy does some reasonable (imho) things with ranges
http://groovy.codehaus.org/Collections

thanks

---
co-chair http://ocjug.org/

Sean Eagan

unread,
Jan 17, 2012, 5:33:54 PM1/17/12
to Ray Tayek, General Dart Discussion
I also like how groovy Ranges extend List, and the literal syntax.
I'm not sure how useful ranges of other Comparables besides int would
be though.

I think a "step" parameter would also be useful.

Maybe something like:

/**
* Literal syntax:
* x..y (x to y)
* x..<y (x to y - 1)
* x.. (x to infinity)
* ..x (x to -infinity)
*/
interface Range extends List<int> {
  /**
* first must not be null
* last defaults to infinity if null
   * step must be > 0, steps toward last even if `last < first`
   */
  Range(int first, [int last, int step/* = 1*/]);

int first; // should be in List instead
int step;

}

Cheers,
Sean Eagan

Ray Tayek

unread,
Jan 18, 2012, 12:26:51 AM1/18/12
to Sean Eagan, General Dart Discussion
At 02:33 PM 1/17/2012, Sean Eagan wrote:
>I also like how groovy Ranges extend List, ...

>Maybe something like:
>
>/**
> * Literal syntax:
> * x..y (x to y)
> * x..<y (x to y - 1)
> * x.. (x to infinity)
> * ..x (x to -infinity)
>*/
>interface Range extends List<int> {
> /**
> * first must not be null
> * last defaults to infinity if null
> * step must be > 0, steps toward last even if `last < first`
> */
> Range(int first, [int last, int step/* = 1*/]);
>
> int first; // should be in List instead
> int step;
>
>}

groovy also has:

To remove the first character of a string we can use Groovy's range
index notation.

def name = 'GROOVY'
def substring = name[1..-1]
assert substring == 'ROOVY'

To remove the last character of a string we can use Groovy's range
index notation.

def name = 'GROOVY'
def substring = name[0..-2]
assert substring == 'GROOV'

thanks


>On Tue, Jan 17, 2012 at 2:23 PM, Ray Tayek <rta...@ca.rr.com> wrote:
> >
> > At 08:53 AM 1/14/2012, Ray Tayek wrote:
> >>
> >> On Nov 21 2011, 2:42 am, Olov Lassus <olov.las...@gmail.com> wrote:
> >> > Ranges has been mentioned on misc before but I figured that it would
> >> > be a nice example to write about anyways. ...
> >
> >
> > groovy does some reasonable (imho) things with ranges

> http://groovy.codehaus.org/Collections ...

---
co-chair http://ocjug.org/

Reply all
Reply to author
Forward
0 new messages