Thread overview
[Issue 5395] New: Interval literals
Feb 09, 2011
Denis Derman
Feb 12, 2011
Denis Derman
Feb 13, 2011
Denis Derman
January 01, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395

           Summary: Interval literals
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: bearophile_hugs@eml.cc


--- Comment #0 from bearophile_hugs@eml.cc 2011-01-01 06:32:05 PST ---
Sometimes it's positive to replace some language feature with good Phobos implementations (like complex numbers), but language design is an iterative process, so sometimes it's positive to go the other way too. Tuples and number intervals are two examples where I think it will be good to add some syntax sugar back into the front-end. This enhancement request is about the number intervals.

I suggest for the two following syntaxes to be seen by the compiler as
equivalent, as syntax sugar of each other:
foreach (i; 0 .. 10)
foreach (i; iota(0, 10))

So I suggest the x..y syntax to become first class and to mean
std.range.iota(x,y).

An extension of the interval literal may allow a step value too:

0 .. 10:2

Once present the interval literal becomes useful to remove a () from lazy
expressions, making them more readable:
reduce!max(map!foo(1 .. 1000))
Instead of:
reduce!max(map!foo(iota(1, 1000)))

If the interval literal becomes first class, it's possible to use it for ranged
types, or interval tests too:
if (x in 5 .. 20) {...}

If iota becomes syntax sugar for the ranged sequence, then the compiler is able
to compile better simple code like this:
foreach (i; iota(0, 10, 2)) {...}

See also bug 4603

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 09, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395


Denis Derman <denis.spir@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |denis.spir@gmail.com


--- Comment #1 from Denis Derman <denis.spir@gmail.com> 2011-02-09 04:52:39 PST ---
(In reply to comment #0)
> I suggest for the two following syntaxes to be seen by the compiler as
> equivalent, as syntax sugar of each other:
> foreach (i; 0 .. 10)
> foreach (i; iota(0, 10))
> 
> So I suggest the x..y syntax to become first class and to mean
> std.range.iota(x,y).

+++

> An extension of the interval literal may allow a step value too:
> 
> 0 .. 10:2

Rather doubtful on this; actually topic of your other enhancement request http://d.puremagic.com/issues/show_bug.cgi?id=4112; see comment there.

> Once present the interval literal becomes useful to remove a () from lazy
> expressions, making them more readable:
> reduce!max(map!foo(1 .. 1000))
> Instead of:
> reduce!max(map!foo(iota(1, 1000)))
> 
> If the interval literal becomes first class, it's possible to use it for ranged
> types, or interval tests too:
> if (x in 5 .. 20) {...}

Yo, just suggested this and the above (both syntaxes are equivalent) on the
mailing list.

> If iota becomes syntax sugar for the ranged sequence, then the compiler is able
> to compile better simple code like this:
> foreach (i; iota(0, 10, 2)) {...}

The important point is that, whatever representation and/or rewriting happens on the implementation side, on the language side i..j provide range-compatible semantics (like arrays). It needs not /be/ an instance of Iota (which may also be rewritten, indeed).

Denis

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 09, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #2 from bearophile_hugs@eml.cc 2011-02-09 10:56:28 PST ---
See also for more arguments:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=129228

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 12, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #3 from bearophile_hugs@eml.cc 2011-02-12 04:56:42 PST ---
Michel Fortin:

> how do you rewrite this using the new proposed syntax:
>
>         auto aa = [iota(a, b, c): 1, iota(d, e): 2];

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 12, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #4 from Denis Derman <denis.spir@gmail.com> 2011-02-12 05:36:01 PST ---
(In reply to comment #3)
> Michel Fortin:
> 
> > how do you rewrite this using the new proposed syntax:
> >
> >         auto aa = [iota(a, b, c): 1, iota(d, e): 2];

Annoying. What about reusing '..' instead? Not obvious, sure, but should not
introduce syntactic issues. The initial proposal of ':' is far to be obvious
anyway, I guess.
   auto interval = 1..9..2;
   auto aa = [a..b..c:1, d..e:2];
Or a single dot (since intervals apply only on ints AFAIK):
   auto interval = 1..9.2;
   auto aa = [a..b.c:1, d..e:2];
But then we get a lexer ambiguity problem. Could be reinterpreted at
compile-time; still, a bit stupid?

Other solution: group it using (). Either () is part of the interval syntax, or
optional in case of possible ambiguity:
   auto interval = 1..9:2;
   auto interval = (1..9:2);
   auto aa = [(a..b:c):1, d..e:2];
   auto aa = [(a..b:c):1, (d..e):2];
I like it (but am not such a fan of saving keystrokes as Bearophile is ;-)

Finally, let it down. Frequence of interval notations in code? Relative frequence of interval notations requiring a step?

Denis

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 12, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #5 from bearophile_hugs@eml.cc 2011-02-12 14:53:19 PST ---
Peter Alexander:

> auto foo = [ 1..10 : 2, 2..20 : 3 ];
>
> Is foo an AA of ranges to ints, or an array of stepped ranges?

Lazy strided intervals as associative array keys is not a common need. But
there are few other situations:
auto r = pred ? 1..10 : 2 : 2..20 : 3;

Where the range syntax is not usable you may use the function from Phobos as
fall-back:
auto r = pred ? iota(1,10,2) : iota(2,20,3);

A possible alternative is to require parentheses where the syntax is ambiguous:
auto foo = [(1..10 : 2), (2..20 : 3)];
auto r = pred ? (1..10 : 2) : (2..20 : 3);

Another alternative is to use .. to separate the stride too:
auto foo = [1..10..2, 2..20..3];
auto r = pred ? 1..10..2 : 2..20..3;

Here I assume that the interval syntax is usable on integral values only, like
ints, uints, chars, wchars, BigInts, etc. For floating point values you use
iota again:
iota(1.0, 10.0, 0.5)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
February 13, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #6 from Denis Derman <denis.spir@gmail.com> 2011-02-12 23:35:51 PST ---
(In reply to comment #3)
> Michel Fortin:
> 
> > how do you rewrite this using the new proposed syntax:
> >
> >         auto aa = [iota(a, b, c): 1, iota(d, e): 2];

I like the proposal by Andrej Mitrovic on the mailing list:

But maybe we could extend the array slice syntax to construct [iota] ranges:

filter!`a % 2 == 0`([1..5])
auto r = [0 .. 5];

So if the slice sits on its own it becomes a range. Or is this too scary/ambiguous?

I don't really like them alone:
filter!`a % 2 == 0`(1..5)
auto r = 0 .. 5;

My comment:

This means basically, for slicing:
   (array expression)~(interval notation) ==> slice operation
This also allows noting a step without any syntax problem:
    [start..end:step]
Finally, as noted by someone, this allows reinterpreting slicing as a special
case of indexing, possibly unifying metamethods opIndex & opSlice, and opening
the door to easier custom rules like multi-dimensional semantics.

The issue is indeed this syntax conflicts with current:
    foreach (n ; i..j)
Too bad we have not had this form from the start...

Denis

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 06, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5395



--- Comment #7 from bearophile_hugs@eml.cc 2011-03-06 09:43:09 PST ---
More comments:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=131378

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------