Andrei:
> But the most important question is: if the rewrite were done, to what extent
> would that improve your use of the language? Integral intervals do occur
> outside foreach and slices, but quite infrequently. In those cases you'd gain
> by replacing iota(a, b) with a..b. Is this significant?<
I can list you why I think an interval syntax is better, but at the end you
need to judge values:
- The basic range syntax is already present in two different situations in the
language, for slices and foreach (switch-case statement use the dot-dot syntax
for a related but different purpose). So D programmers don't need to learn a
new syntax, the cognitive cost is probably negative.
- The 1 .. 5 syntax is present in math too (even if it often means a set closed
on the right too).
- There is no need to learn to use a function with a weird syntax like iota,
coming from APL. This makes Phobos and learning D a bit simpler.
- Both 1..5 and iota(1,5) are able to support the "in" operator. This is good
because D doesn't support the a<X<b Python syntax. X in a..b will mean a<=X<b.
- If the compiler front-end becomes aware of the interval syntax, it is able to
perform "3 in 1..10" at compile-time too, simplifying sub-expressions even when
they are inside other run-time expressions.
- With the interval syntax there is no need to import std.range, that's
necessary for iota().
- the a..b syntax is shorter and a bit less noisy: array(1..5) compared to
array(iota(1,5)).
- The a..b syntax is extendible to cover the third stride argument of iota(). I
suggest a..b:c (The stride syntax is later usable for arrays too if the stride
is a compile-time constant). Python shows several nice usages of the stride
argument.
- Currently foreach(i; retro(iota(...))) or even foreach(i; iota(...)) are not
as fast as foreach(i; ...). I hope this interval syntax will help DMD digest a
lazy interval more efficiently.
- Interesting point, to translate this to interval syntax: iota(1.,-5.) it
becomes 1...5. that's a mess. You need zeros: 1.0 .. 5.0
- Another interesting point, currently the semantics of iota() and the interval
in foreach are not the same, only the second loop here raises an exception:
import std.stdio, std.range;
void main() {
foreach (x; 1 .. -5)
writeln(x);
foreach (x; iota(1, -5))
writeln(x);
}
In my opinion iota() semantics here must be the same as the foreach interval,
and yield an empty iterable with no errors:
http://d.puremagic.com/issues/show_bug.cgi?id=4603
I like the interval literal syntax for static things too, example:
http://d.puremagic.com/issues/show_bug.cgi?id=4085
static foreach (x; 1 .. -5)
A first class literal syntax in D (typeid(typeof(1..5)) gives a new type) may
become useful for slices too in objects/structs, this is Python 2.6 code:
class Foo(object):
def __getitem__(self, key):
print key
f = Foo()
f[1:2]
Output:
slice(1, 2, None)
Bye,
bearophile