On 02/14/2011 04:11 PM, Steven Schveighoffer wrote:
On Fri, 11 Feb 2011 19:06:48 -0500, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> wrote:

On 2/11/11 8:31 AM, Bruno Medeiros wrote:
On 04/02/2011 16:14, Eric Poggel wrote:
On 2/3/2011 10:20 PM, Andrei Alexandrescu wrote:
At this point there is no turning back from ranges, unless we come about
with an even better idea (I discussed one with Walter but we're not
pursuing it yet).

Care to elaborate on the new idea? Or at least a quick summary so we're
not all left wondering?

That comment left me curious as well...

The discussed idea went as follows.

Currently we have r.front and r.back for accessing the first and last
element, and r[n] for an arbitrary element.

Plus, r[n] is extremely flexible (opIndex, opIndexAssign, opIndexOpAssign...
awesome level of control... just perfect). So then I thought, how about
unifying everything?

Imagine we gave up on r.front and r.back. Poof. They disappeared. Now we
define two entities "first" and last" such that r[first] and r[last] refer
the first and last elements in the range. Now we have the situ:

- Input and forward ranges statically allow only r[first]

- Bidirectional ranges allow r[first] and r[last]

- Random-access ranges allow r[first], r[last], and r[n] for integrals n

Now we have a unified way of referring to elements in ranges. Walter's
excellent follow-up is that the compiler could use lowering such that you
don't even need to use first and last. You'd just use r[0] and r[$ - 1] and
the compiler would take care of handling these special cases.

er... I don't like this. 0 does not necessarily mean first element. A map has
arbitrary keys.

That is, even though it potentially could be unambiguous (the compiler could
ensure that it is indeed a range type before allowing the conversion of 0 to
first), there would be confusion where [0] *didn't* mean first element.


Advantages: unified syntax, increased flexibility with opIndexAssign and
opIndexOpAssign. Disadvantages: breaks all range-oriented code out there.

opIndexOpAssign is really the only improvement. I think code-wise, things would
get uglier. For example, in a bidirectional range, front() and back() do not
simply translate to some index that can be applied to another function.
However, in random-access ranges, front() can simply be defined as opIndex. So
for, random-access ranges, code gets shorter, but not necessarily simpler
(slightly less boilerplate) but bidirectional ranges get much uglier (static
ifs and the like).

But I agree the opIndexOpAssign is a missing piece for front and back.

But let's think about something else -- you want first and last, but front and
back also work. What if we continued to use front and back, kept the current
functions, but treated r[front] and r[back] as you say? Then, you'd have some
rule for r[front] like:

1. if front() is defined, translates to r.front()
2. if opIndex is defined, translates to r.opIndex[0], although I would prefer
some symbol other than 0, because I'd like to use it on a custom map type to
mean "front element".

And then all existing ranges still work, with the new syntax, and you can keep
the clear separation of functions for when it makes sense.

I'd also like r.rest or r[rest] (meaning lisp's cdr = all but first). Rather frequent needs in functions à la reduce (take first element as seed, then iterate/recurse on rest), and recursive functional algorithms in general. What do you think?

functional 'in':

    bool contains (E) (E[] elements, E element) {
        if (elements.length == 0)
            return false;
        if (elements[0] == element)
            return true;
        return contains(elements.rest(), element);
   }

[By the way, I'm looking for a clear explanation of how tail recursion elimination is typically implemented: pointer welcome off list if you have that.]

Denis
--
_________________
vita es estrany
spir.wikidot.com

Reply via email to