April 10, 2005
> Inserting for lvalues is OK and kinda neat, but inserting for rvalues ?
> (it would most definitely have to be documented in <blink> tags, or so)
>
> And like has been mentioned over and over, it's not even a .init/new -
> but just a dummy entry full of zeroes ? (just allocated with calloc...)

Hm. You are right. Perhaps this should be changed. Everything i needed until now was a function like this:

T lookup(Key key, T defaultValue)

which returns the value for key or defaultValue if key isn't in the map. No fancy inserting...

Ciao
uwe
April 10, 2005
Ben Hinkle wrote:

> The word-count example at the bottom of the Array doc has something like
> count[word]++;
> which only works because the counts are ints and start at 0.

I think it would work the same if rvalue defaulted to zero,
and lvalue inserted the new value ? Assuming that ++ expands
to something similar to: "count[word] = count[word] + 1;" ?

--anders
April 10, 2005
> I think it would work the same if rvalue defaulted to zero,
> and lvalue inserted the new value ? Assuming that ++ expands
> to something similar to: "count[word] = count[word] + 1;" ?

But ++ (and += and friends) is guaranteed to evaluate the operand only once...

Ciao
uwe
April 10, 2005
Uwe Salomon wrote:

>> I think it would work the same if rvalue defaulted to zero,
>> and lvalue inserted the new value ? Assuming that ++ expands
>> to something similar to: "count[word] = count[word] + 1;" ?
> 
> But ++ (and += and friends) is guaranteed to evaluate the operand only  once...

Maybe it really is broken by design, then. That's too bad...

--anders
April 14, 2005
"Ben Hinkle" <Ben_member@pathlink.com> wrote in message news:d3bg60$2n7q$1@digitaldaemon.com...
> In article <opso0b4nv26yjbe6@sandmann.maerchenwald.net>, Uwe Salomon says...
>>
>>>> If you
>>>> would change the behaviour of [], there would be no operator
>>>> for "give
>>>> me
>>>> the value to key X, or the default if there isn't an X in the
>>>> map".
>>>
>>> No! "Giving default" if X not exists and "inserting if not
>>> exists" are
>>> very
>>> different. Let's reading aa[not_exist_key] give default, but not
>>> write
>>> any data
>>> to AA. This is side effect. After this "in" operator useless.
>>> Information about
>>> "was element exists in AA" lost.
>>
>>Jep, sorry. I meant "lookup X and insert default if X doesn't
>>exist". Thus
>>"in" only does a lookup, and "[]" inserts if necessary.
>
> My preferred AA api, as posted a while ago to Matthew's "in
> stinks" thread:
> bit opIn(Key key) // possibly return value* instead

Agree, apart from Value* part

> Value opIndex(Key key) // throws on missing key

Agree

> void opIndexAssign(Value value, Key key) // insert

Agree

> bit contains(Key key, out Value value)

Agree. (I think it was me that suggested this one, so am bound to agree <g>)

> void remove(Key key) // ignores missing key

Don't agree with ignoring missing thing, although not 100% about it

> Value* insert(Key key) // lookup and insert if not present

Don't get this? What get's inserted? Surely it needs a second param, as in

<whatever> insert(Key key, Value value):

??

Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?

> .. rest as before except "delete" is removed...

Agree


> -Ben
>
> ps - it would be nice to hear boo from Walter what chances any
> changes to AAs
> have of happening.

Seconded.

> I have the feeling the chances are around 10% or less.

Optimist!



April 14, 2005
>> My preferred AA api, as posted a while ago to Matthew's "in stinks"
>> thread:
>> bit opIn(Key key) // possibly return value* instead
>
> Agree, apart from Value* part

my preference, too. I haven't thought too hard about use cases for the value* form.

>> Value opIndex(Key key) // throws on missing key
>
> Agree
>
>> void opIndexAssign(Value value, Key key) // insert
>
> Agree
>
>> bit contains(Key key, out Value value)
>
> Agree. (I think it was me that suggested this one, so am bound to agree <g>)

I should have been more careful in attributing the different ideas since my saying "my preferred API" implicitly means I came up with the API, which isn't right.

>> void remove(Key key) // ignores missing key
>
> Don't agree with ignoring missing thing, although not 100% about it

I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.

>> Value* insert(Key key) // lookup and insert if not present
>
> Don't get this? What get's inserted? Surely it needs a second param, as in
>
> <whatever> insert(Key key, Value value):
>
> ??
>
> Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?

I have a feeling Walter likes the current behavior because of the example in
the Array section with the magic line
  count[word]++;
And so I wanted to supply something similar and the best way I could see was
"insert":
  (*count.insert(word))++
A better name would help. I thought of calling it insertKey but then I
shortened it to just insert, perhaps by mistake. Having insert take a key
and value makes it the effectively the same as opIndexAssign, which seems
redundant. If you scroll up you'll see I put the comment "// insert" next to
opIndexAssign so arguably this "insert" name needs to change.


April 14, 2005
>>> bit contains(Key key, out Value value)
>>
>> Agree. (I think it was me that suggested this one, so am bound to agree <g>)
>
> I should have been more careful in attributing the different ideas since my saying "my preferred API" implicitly means I came up with the API, which isn't right.

It was no problem. Just yanking ya chain. ;)

>>> void remove(Key key) // ignores missing key
>>
>> Don't agree with ignoring missing thing, although not 100% about it
>
> I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.

I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.

>>> Value* insert(Key key) // lookup and insert if not present
>>
>> Don't get this? What get's inserted? Surely it needs a second param, as in
>>
>> <whatever> insert(Key key, Value value):
>>
>> ??
>>
>> Now, as to <whatever> is, that depends on how you respond to the above question. My suspicion is that you've used Value* so that some can write to it, which I think sucks, I'm afraid. I really don't think D should be flirting with pointers in such cases. Also, what's wrong with the (Key, Value) syntax?
>
> I have a feeling Walter likes the current behavior because of the example in the Array section with the magic line
>  count[word]++;
> And so I wanted to supply something similar and the best way I could see was "insert":
>  (*count.insert(word))++
> A better name would help. I thought of calling it insertKey but then I shortened it to just insert, perhaps by
> mistake. Having insert take a key and value makes it the effectively the same as opIndexAssign, which seems redundant.
> If you scroll up you'll see I put the comment "// insert" next to opIndexAssign so arguably this "insert" name needs
> to change.

Ok. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>)

I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>



April 14, 2005
>>>> void remove(Key key) // ignores missing key
>>>
>>> Don't agree with ignoring missing thing, although not 100% about it
>>
>> I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.
>
> I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.

To elaborate on my first reply, to me removing a key that isn't in the array is similar to closing a stream that is already closed. I see both situations as no-ops since the requested end-state is already satisfied. The basic principle is "no harm no foul". I'd be interesting in more opinions, too, though.

>>>> Value* insert(Key key) // lookup and insert if not present
>>>
>>> Don't get this? What get's inserted? Surely it needs a second param, as in
>>>
>>> <whatever> insert(Key key, Value value):
>
> Ok. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>)

Here's the API with more details/examples. The array is variable "x", the key "key" and the value "val".

function:
  bit opIn(Key key)
example:
  if (key in x) {...}
  Returns true iff key is in x.

function:
  Value opIndex(Key key) (note this is internal to the compiler impl and
isn't user visible)
example:
  val = x[key];
  Lookup and return the value for key. Throws an exeption if key is not in
x. Result is not an lvalue.

function:
  void opIndexAssign(Value val, Key key) (compiler internal impl)
example:
  x[key] = val;
  Associates val with key. Inserts if key is not in x and otherwise
overwrites previous value. This is the only syntax where x[key] can be used
as an lvalue.

function:
  bit contains(Key key, out Value val)
example:
  if (x.contains(key,val)) {...}
  Returns true iff key is in x. If key is in x assigns the associated value
to val.

function:
  void remove(Key key)
example:
  x.remove(key);
  Removes key from x if key is in x.

function:
  Value* insert(Key key)
examples:
  (*x.insert(key)) += 10;
  foo(*x.insert(key)) // where foo is void foo(out Value val);
  If key is in x returns a pointer to the associated value and otherwise
insert key with the default value and return a pointer to it. Note that
x[key] = value is equivalent to *x.insert(key) = value;

I'm tempted to add some more like
  Value replace(Key key, Value value)
  Value* query(Key key) // return null if key not in x
but I'll hold off on those. They would be nice to have IMO. The reason for
adding more sophisticated functions for AAs than dynamic arrays is that
writing multiple lookups for AA is significantly more expensive for
performance than dynamic arrays.

> I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>

Exposing the pointer would only happen when you can't use the x[key]=value syntax. The "advanced maneuver" of inserting, initializing and returning an lvalue needs to be possible and that's where the pointers/references come in. If D had references or out-references or whatever then I agree it probably would be nice to remove the pointer stuff. Or if D had a different syntax than x[key] for indicating it should return an lvalue that would work, too.


April 16, 2005
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:d3lulk$11pd$1@digitaldaemon.com...
>
>>>>> void remove(Key key) // ignores missing key
>>>>
>>>> Don't agree with ignoring missing thing, although not 100% about it
>>>
>>> I figured removing something that doesn't exist is a no-op. The post-condition that the AA doesn't contain the key is true.
>>
>> I'm still feeling a bit unsure, but I always err on the side of strictness. If people aren't too tired by now, I'd be interested in hearing thoughts on the matter.
>
> To elaborate on my first reply, to me removing a key that isn't in the array is similar to closing a stream that is already closed. I see both situations as no-ops since the requested end-state is already satisfied. The basic principle is "no harm no foul". I'd be interesting in more opinions, too, though.

Impishly mixing threads of contention(/contentiousness), I'd say that if it's part of the contract of remove(), then there's no problem. ;)

>>>>> Value* insert(Key key) // lookup and insert if not present
>>>>
>>>> Don't get this? What get's inserted? Surely it needs a second param, as in
>>>>
>>>> <whatever> insert(Key key, Value value):
>>
>> Ok. Maybe we need to have code samples / use cases for all the proposed syntax? (I'm such a dumb ass, as I really need to see code in order to think about it <g>)
>
> Here's the API with more details/examples. The array is variable "x", the key "key" and the value "val".
>
> function:
>  bit opIn(Key key)
> example:
>  if (key in x) {...}
>  Returns true iff key is in x.

Totally agree

> function:
>  Value opIndex(Key key) (note this is internal to the compiler
> impl and isn't user visible)
> example:
>  val = x[key];
>  Lookup and return the value for key. Throws an exeption if key is
> not in x. Result is not an lvalue.

Totally agree.

> function:
>  void opIndexAssign(Value val, Key key) (compiler internal impl)
> example:
>  x[key] = val;
>  Associates val with key. Inserts if key is not in x and otherwise
> overwrites previous value. This is the only syntax where x[key]
> can be used as an lvalue.

Totally agree

> function:
>  bit contains(Key key, out Value val)
> example:
>  if (x.contains(key,val)) {...}
>  Returns true iff key is in x. If key is in x assigns the
> associated value to val.

Agree, except I think there should also be an overload that doesn't take the out value, i.e. is just a method-form equivalent to "in"

> function:
>  void remove(Key key)
> example:
>  x.remove(key);
>  Removes key from x if key is in x.

Totally agree

> function:
>  Value* insert(Key key)
> examples:
>  (*x.insert(key)) += 10;
>  foo(*x.insert(key)) // where foo is void foo(out Value val);
>  If key is in x returns a pointer to the associated value and
> otherwise insert key with the default value and return a pointer
> to it. Note that x[key] = value is equivalent to *x.insert(key) =
> value;

Don't like it, I'm afraid. Been reading up on some more 'advanced' Python recently, and the use of * there seems exceedingly foreign and hacky. This gives me the very same impression. I respectfully submit that both your examples syntactically suck.

I see where you're coming from, though, which I'd not done earlier in the thread. What you're looking for is how to support a somewhat-analoguous behaviour for other operations as exists for []=. In C++ we'd return a reference from insert() and it'd be simple.

Do I rightly recall recent calls for returning lvalues from functions? If so, that'd be the right approach. If not, I think your *-hack is kind of sticking plaster on a deeper inadequacy in D.

I feel/hope that there's a solution to the wider issue, but nothing's coming to mind at the moment.

I suggest this one is marked for further discussion.

> I'm tempted to add some more like
>  Value replace(Key key, Value value)
>  Value* query(Key key) // return null if key not in x
> but I'll hold off on those. They would be nice to have IMO. The
> reason for adding more sophisticated functions for AAs than
> dynamic arrays is that writing multiple lookups for AA is
> significantly more expensive for performance than dynamic arrays.
>
>> I just have a really bad feeling about pointers being anywhere in the syntax for D for things that do not directly pertain to talking to C APIs. Otherwise, why don't we just drop the ambiguities that come with references, go with pointers for objects, and clear up the identity/equality issue? <g>
>
> Exposing the pointer would only happen when you can't use the x[key]=value syntax. The "advanced maneuver" of inserting, initializing and returning an lvalue needs to be possible and that's where the pointers/references come in. If D had references or out-references or whatever then I agree it probably would be nice to remove the pointer stuff. Or if D had a different syntax than x[key] for indicating it should return an lvalue that would work, too.

Both interesting. I suspect Walter might have one of his inspirations on this one, if we can sufficiently convince him that the pointer stuff is un appealing.



1 2 3
Next ›   Last »