Revised RFC on range design for D2

Bill Baxter wbaxter at gmail.com
Fri Oct 3 12:32:26 PDT 2008


On Fri, Oct 3, 2008 at 11:02 PM, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> Sergey Gromov wrote:
>>
>> Thu, 02 Oct 2008 15:03:42 -0500,
>> Andrei Alexandrescu wrote:
>>>
>>> Yah, overloaded ops are due for an overhaul. I'm almost afraid to ask...
>>> any ideas? :o)
>>>
>>> One goal is to fix opIndexAssign and make it work similar to the way it
>>> works in arrays, e.g. a[b] += c. Indexing into hash tables is a good test
>>> bed.
>>
>> What's wrong with a.opIndexAssign(b, a.opIndex(b) + c)?
>
> One problem is that for a hashtable that does not have b yet, opIndex will
> throw an exception.

I don't see why you expect   a[b] += c to work on a key for which a[b]
is undefined.  If it's undefined how can you increment it?

Unless you've defined your accessor for undefined keys to return some
other value.  And if it returns some other value then Sergey's rule is
fine.

Sparse matrices are a good example of a hash-like data-structure that
should return a default value (namely zero) for unset keys.  For such
a sparse matrix      a.opIndexAssign(b, a.opIndex(b) + c)   will work
fine.


> Another problem (assuming the above is fixed) is that b will be looked up
> twice in the hash.

That is a problem.  But like Sergey said, if performance is your #1
concern then return references.

Though, that solution is a little problematic for the sparse matrices.
 In order to return a reference to an element that didn't previously
exist, you must create it.  But if you're just scanning through your
sparse matrix printing out the values with a[b], you don't expect to
end up with a dense matrix full of zeros!  In a C++ lib you'd probably
provide an lvalue-returning operator[] and another function that
returns just an rvalue.

Ooh, how about passing in the manipulator @= function somehow?  Either
delegate or template alias param.

Example for sparse matrix case:
// Called for  a[b] @= c type operations
void opIndexUpdate(void delegate(ref ValueType val) updater, uint idx) {
      float *ptr = getPtrToElement(idx);  // creates new zero element if needed
      updater(*ptr);
      // here you can veto the change
      // or throw an overflow exception
      // or clamp *ptr
      // or round it
      //  or whatever you want...
}

Compiler would generate the different updaters needed for the various
@= operations.

Maybe with a template alias param there'd maybe be better hope of the
compiler being able to inline it all, but then you have the no
inheritance problem.

void opIndexUpdate(alias updater)(uint idx) {
      float *ptr = getPtrToElement(idx);  // creates new zero element if needed
      updater(*ptr);
}

--bb


More information about the Digitalmars-d-announce mailing list