March 08, 2005
> Hear Hear!

Hear hear what?

> It just doesn't make sense to wrap a try/catch around hashmap lookups,
> where a
> missing entry is perfectly legitimate. The performance hit would be
> even less
> attractive.

I don't recall a single post in the last week that's even hinted at such a thing. Naturally that would be total crap. The throwing [] has been suggested as an inprovement to the semantics of the existing subscript operation _in combination with_ the addition of a non-throwing, boolean returning 'in' and a non-throwing, boolean returning lookup(in key, out value) method.

Can we please all either get back on point, or get off the thread?! This stuff's bordering on the peurile

>
>
>
> In article <d0j1fc$ueh$1@digitaldaemon.com>, Mike Parker says...
>>
>>Ben Hinkle wrote:
>>
>>> My vote would be for 3 since looking up a key that isn't in the
>>> array is the AA
>>> equivalent to indexing a dynamic array outside of its bounds. Since
>>> indexing out
>>> of bounds throws an exception (in debug mode) so should invalid key
>>> lookup.
>>
>>I disagree. An out of bounds array index is an exceptional case
>>because
>>the size of the array is, usually, a known quantity - i.e. all members
>>of the set of numbers from 0...n are valid, and n *must* be known
>>during
>>the allocation of the array. Unassigned keys in a hashmap are not an
>>exceptional case because for hashmaps there is no valid set of keys
>>(in
>>the general case) that is guaranteed to be known at runtime. Besides
>>which, hasmaps are quite often used as a form of registry where the
>>case
>>of unassigned keys is common.
>>
>>I'm in the camp that advocates throwing exceptions only in exceptional
>>circumstances, and not as a general catch-all failure signal. If you
>>imagine a world where exceptions are never caught, what are some
>>failure
>>cases which, the majority of the time, would be an acceptable reason
>>to
>>terminate the program? Any answers you come up with are good
>>candidated
>>to define as 'exceptional'. In my book, hashmap lookup failures do not
>>pass that test.
>>
>>Just to push my point further, there is not one case where an out of
>>bounds array index is acceptable. And in every case the developer
>>would
>>certainly want to know if an attempt to index an out of bounds array
>>were made. In our imaginary world of uncaught exceptions, this is a
>>great time to terminate the program. Yet there are a large number of
>>hashmap use cases where you would not want your application to
>>terminate
>>because a particular key wasn't assigned. Imagine a plugin system that
>>loads plugins on demand. Of course the user should be notified that a
>>particular plugin isn't available to load - but does that pass the
>>test
>>as an acceptable reason to terminate the application? Not in the
>>genral
>>case, it is in the application specific domain and therefore it is not
>>exceptional. And when a failure case is not exceptional, then a
>>testable
>>value (a boolean or null, for example) should be returned instead so
>>that the application can decide whether or not to terminate.
>>
>>True, you can choose to catch an exception and do nothing with it, but
>>in my book that is poor design, particularly in a language like D
>>which
>>has no mechanism that requires you to catch exceptions, or even
>>declare
>>that a particular method or operation throws one. It's too easy to
>>overlook an exception here or there. If my production software
>>terminates, it had better be due to an exceptional case.
>
>
> 


March 08, 2005
In article <d0j1fc$ueh$1@digitaldaemon.com>, Mike Parker says...
>
>Ben Hinkle wrote:
>
>> My vote would be for 3 since looking up a key that isn't in the array is the AA equivalent to indexing a dynamic array outside of its bounds. Since indexing out of bounds throws an exception (in debug mode) so should invalid key lookup.
>
>I disagree. An out of bounds array index is an exceptional case because the size of the array is, usually, a known quantity - i.e. all members of the set of numbers from 0...n are valid, and n *must* be known during the allocation of the array.

Dynamic arrays grow and shrink all the time. Same thing with adding and removing keys from an AA. The only difference (conceptually) is that dynamic arrays have a continuous block of integer keys. But I don't see why that matters.

>Unassigned keys in a hashmap are not an exceptional case because for hashmaps there is no valid set of keys (in the general case) that is guaranteed to be known at runtime.

Same for dynamic arrays. An empty array should have no valid lookups. Let me put it this way, when you look up the phone number of someone in the phone book and it isn't there, do you dial a random number, or make up a phone number and write it into the phone book? I doubt it.

>Besides which, hasmaps are quite often used as a form of registry where the case of unassigned keys is common.

ok, that's fine. For those cases one can use the function that doesn't throw - what we know as "in" today. The question here is what to do with expressions of the form aa[key] that must return something of the value type.

>I'm in the camp that advocates throwing exceptions only in exceptional circumstances, and not as a general catch-all failure signal. If you imagine a world where exceptions are never caught, what are some failure cases which, the majority of the time, would be an acceptable reason to terminate the program? Any answers you come up with are good candidated to define as 'exceptional'. In my book, hashmap lookup failures do not pass that test.

True throwing exceptions shouldn't be done willy nilly. So what do you propose? I take it your are comfortable with the current behavior? I'm

>Just to push my point further, there is not one case where an out of bounds array index is acceptable. And in every case the developer would certainly want to know if an attempt to index an out of bounds array were made. In our imaginary world of uncaught exceptions, this is a great time to terminate the program. Yet there are a large number of hashmap use cases where you would not want your application to terminate because a particular key wasn't assigned.

Again, there are other ways of safely looking up a key that might not be in the array.

>Imagine a plugin system that loads plugins on demand. Of course the user should be notified that a particular plugin isn't available to load - but does that pass the test as an acceptable reason to terminate the application? Not in the genral case, it is in the application specific domain and therefore it is not exceptional. And when a failure case is not exceptional, then a testable value (a boolean or null, for example) should be returned instead so that the application can decide whether or not to terminate.

ahh - I think I see the miscommunication. That last sentance says something about returning a testable value - which to me is what "in" is for. We are talking about two different functions. I totally agree there should be an exception-free key lookup. It's just that aa[key] is not that function.

>True, you can choose to catch an exception and do nothing with it, but in my book that is poor design, particularly in a language like D which has no mechanism that requires you to catch exceptions, or even declare that a particular method or operation throws one. It's too easy to overlook an exception here or there. If my production software terminates, it had better be due to an exceptional case.

agreed.


March 08, 2005
In article <d0j4qk$12e5$2@digitaldaemon.com>, Matthew says...
>
>> Hear Hear!
>
>Hear hear what?


"Exceptions are for exceptional cases" ~ a non-existant entry in an HashMap is not exceptional in and of itself. Period.


>> It just doesn't make sense to wrap a try/catch around hashmap lookups,
>> where a
>> missing entry is perfectly legitimate. The performance hit would be
>> even less
>> attractive.
>
>I don't recall a single post in the last week that's even hinted at such a thing. Naturally that would be total crap.


Guess I missed a whole lot of posts.


>The throwing [] has been suggested as an inprovement to the semantics of the existing subscript operation _in combination with_ the addition of a non-throwing, boolean returning 'in' and a non-throwing, boolean returning lookup(in key, out value) method.


OK. Thanks for the catchup. You'll perhaps forgive me for noticing that three seperate and distinct means to 'lookup' an AA entry, and the fact they apparently have differing behaviour, might seem a tad odd and unweildly? Perhaps we should stick to the lookup() method?


>Can we please all either get back on point, or get off the thread?! This stuff's bordering on the peurile


<cough> Ahem. Is it really? Or are you having a particularly bad day?


>
>>
>>
>>
>> In article <d0j1fc$ueh$1@digitaldaemon.com>, Mike Parker says...
>>>
>>>Ben Hinkle wrote:
>>>
>>>> My vote would be for 3 since looking up a key that isn't in the
>>>> array is the AA
>>>> equivalent to indexing a dynamic array outside of its bounds. Since
>>>> indexing out
>>>> of bounds throws an exception (in debug mode) so should invalid key
>>>> lookup.
>>>
>>>I disagree. An out of bounds array index is an exceptional case
>>>because
>>>the size of the array is, usually, a known quantity - i.e. all members
>>>of the set of numbers from 0...n are valid, and n *must* be known
>>>during
>>>the allocation of the array. Unassigned keys in a hashmap are not an
>>>exceptional case because for hashmaps there is no valid set of keys
>>>(in
>>>the general case) that is guaranteed to be known at runtime. Besides
>>>which, hasmaps are quite often used as a form of registry where the
>>>case
>>>of unassigned keys is common.
>>>
>>>I'm in the camp that advocates throwing exceptions only in exceptional
>>>circumstances, and not as a general catch-all failure signal. If you
>>>imagine a world where exceptions are never caught, what are some
>>>failure
>>>cases which, the majority of the time, would be an acceptable reason
>>>to
>>>terminate the program? Any answers you come up with are good
>>>candidated
>>>to define as 'exceptional'. In my book, hashmap lookup failures do not
>>>pass that test.
>>>
>>>Just to push my point further, there is not one case where an out of
>>>bounds array index is acceptable. And in every case the developer
>>>would
>>>certainly want to know if an attempt to index an out of bounds array
>>>were made. In our imaginary world of uncaught exceptions, this is a
>>>great time to terminate the program. Yet there are a large number of
>>>hashmap use cases where you would not want your application to
>>>terminate
>>>because a particular key wasn't assigned. Imagine a plugin system that
>>>loads plugins on demand. Of course the user should be notified that a
>>>particular plugin isn't available to load - but does that pass the
>>>test
>>>as an acceptable reason to terminate the application? Not in the
>>>genral
>>>case, it is in the application specific domain and therefore it is not
>>>exceptional. And when a failure case is not exceptional, then a
>>>testable
>>>value (a boolean or null, for example) should be returned instead so
>>>that the application can decide whether or not to terminate.
>>>
>>>True, you can choose to catch an exception and do nothing with it, but
>>>in my book that is poor design, particularly in a language like D
>>>which
>>>has no mechanism that requires you to catch exceptions, or even
>>>declare
>>>that a particular method or operation throws one. It's too easy to
>>>overlook an exception here or there. If my production software
>>>terminates, it had better be due to an exceptional case.
>>
>>
>> 
>
>


March 08, 2005
"Kris" <Kris_member@pathlink.com> wrote in message news:d0j81b$167m$1@digitaldaemon.com...
> In article <d0j4qk$12e5$2@digitaldaemon.com>, Matthew says...
>>
>>> Hear Hear!
>>
>>Hear hear what?
>
>
> "Exceptions are for exceptional cases" ~ a non-existant entry in an
> HashMap is
> not exceptional in and of itself. Period.

Correct.

But trying to get the value of a non-existant entry is an exceptional condition. Axiomatic.

>>The throwing [] has been
>>suggested as an inprovement to the semantics of the existing subscript
>>operation _in combination with_ the addition of a non-throwing,
>>boolean
>>returning 'in' and a non-throwing, boolean returning lookup(in key,
>>out
>>value) method.
>
>
> OK. Thanks for the catchup. You'll perhaps forgive me for noticing
> that three
> seperate and distinct means to 'lookup' an AA entry, and the fact they
> apparently have differing behaviour, might seem a tad odd and
> unweildly?

Better to have 10 simple, well-defined, discoverable, sensible things that just do their jobs in the way any sane person would expect than shoehorning many disjoint tasks into one.

> Perhaps
> we should stick to the lookup() method?

I really don't see the big deal.

int[char[]]    vice;

1. Ask if something exists, without wanting to get hold of it _now_

    if("arse" in vice)
    {
        ... do something in response to knowing that your "arse" is in
the "vice"

2. Ask if something exists, and get hold of it if it does

    int    value;

    if(vice.lookup("arse", value))
    {
        ... do something with the value of your "arse"

3. "Knowing" that something exists, simply get hold of it

    int    value    =    vice["arse"];

    If vice does not have your "arse" in it, then it throws an
exception. What else can it sensibly do?


I use associative containers in several languages, including C++ (auto-inserts) and Ruby (returns default), and am constantly hrumphing around and cursing stupid language designers. Associative containers in these languages do hidden things. Therefore they're shite. Period.

The above scheme does *nothing* hidden, therefore it is _not_ shite. Might not be to everyone's tastes, but doing nothing hidden is more important. And __puh-leezze__ no-one say that throwing an exception is (necessarily) hidden behaviour. If its part of the [] operators contract, then it ain't hidden!

Incidentally, I couldn't give a rat's about the syntax. (I'd be quite happy if AAs lost much/all of their in-built-ness.)

For example, in std.openrj, a record has the following methods:

    bool        hasField(); // aka 'in'
    Field       findField(); // aka lookup()
    Field       getField(); // aka []

This avoids the slight complexity of lookup because a Field, being of class type, can be represented in its does-not-exist form as a null. Naturally, in DTL the containers cannot do the same. (I forget exactly how they do it at the mo ... blush)

btw, Record also provides operator [], which just calls getField().


>>Can we please all either get back on point, or get off the thread?!
>>This
>>stuff's bordering on the peurile
>
>
> <cough> Ahem. Is it really? Or are you having a particularly bad day?

Not bad, but obviously somewhat out of kilter.

I know you're up to it, though, my rumbustious friend.



March 08, 2005
In article <d0j917$173j$1@digitaldaemon.com>, Matthew says... <snip>
>I use associative containers in several languages, including C++ (auto-inserts) and Ruby (returns default), and am constantly hrumphing around and cursing stupid language designers. Associative containers in these languages do hidden things. Therefore they're shite. Period.
>
>The above scheme does *nothing* hidden, therefore it is _not_ shite. Might not be to everyone's tastes, but doing nothing hidden is more important. And __puh-leezze__ no-one say that throwing an exception is (necessarily) hidden behaviour. If its part of the [] operators contract, then it ain't hidden!
>
>Incidentally, I couldn't give a rat's about the syntax. (I'd be quite happy if AAs lost much/all of their in-built-ness.)


Aye; I'm with you, on all the above.



>> <cough> Ahem. Is it really? Or are you having a particularly bad day?
>
>Not bad, but obviously somewhat out of kilter.
>
>I know you're up to it, though, my rumbustious friend.


Naturally ~ I can certainly dish it out in profuse conglomerations

(talking of which: does anyone recall an old Dudley & Moore skit about "going to sea on one of Winston Churchill nose bogeys" ?)


March 08, 2005
> Naturally ~ I can certainly dish it out in profuse conglomerations
>
> (talking of which: does anyone recall an old Dudley & Moore skit about
> "going to
> sea on one of Winston Churchill nose bogeys" ?)

I don't, but you got a laugh out of me anyway. :-)


March 08, 2005
bamb00 wrote:

>>>Javascript does it just that way, too.
>>
>>Does what ? Set keys on lookup ? No, it doesn't.

> C++'s map does it for sure , why I have no idea, seems like a horrible idea
> to me as well.  Just wanted to throw my vote in the 'No AA Writing on
> lookup' camp.

Throwing exceptions on missing keys is *equally* bad,
in my opinion. It would also stop me from using hashes
the way that I am used, and I'd have to continue with
the workaround that's currently needed due to setting.

I guess it boils down to whether you consider an
empty array to be full of valid lookups, or not...
To me, a dynamic array is full of .init values
so then it makes sense that associative arrays
should also be full of .init values as well.


In the end, I'll just continue to write code like today.
value = (key in hash) ? hash[key] : null;

It's also the only form that has survived for a while,
even if it does do a double lookup in the hash table.
(but actually using "key.init" instead of null above
does not work, due to a horrible init-related bug)

--anders
March 08, 2005
Matthew wrote:

> Same here. And trying to get a value out of an associative container that does not exist is exactly that, exceptional. (Or it certainly should be.)

I just can't agree with this. A missing key is simply a missing key. See below.


> Absolute nonsense.
> 
> I'm bugging out now, because I fear we're so far apart that there's no point wasting our breaths. :-(

Too bad, because I think this is something that needs to be discussed. Associative arrays are an integral part of the language that will be used frequently. And maybe the fact that you and I are so far apart indicates that other people are going to have extremely different views on the issue as well.

The problem, as I see it, is twofold. First, is the [] operator. This causes people to view aa's in the same light as normal arrays. From that perspective, I can understand how aa["missing key"] can be construed as functionally equivalent to array[out_of_bounds_index]. I see it the former being more like a substitute for Hashmap.get("missing key") in Java, which always returns null and which I have never heard anyone argue should being throwing an exception instead.

The second problem is that aas allow any sort of value to be stored. If it allowed only class objects, then we wouldn't need the pointer syntax which 'in' currently returns (which seems to be the bit that ignited the discussion in the first place). But that's nasty. I surely don't want to wrap my struct instances and integrals in a class just to put them in an aa.

In my opinion, aas should function thusly:

boolean contains = (key in aa);
int* val = aa["key"]; // return null if missing

I don't see a problem with using pointers as return values, as it eliminates the requirement that all aa values be objects, and pointers are a part of the language anyway.

Perhaps I'm wrong viewing associative rays in the same light as Java's Hashmaps. But in my mind it's a natural way to look at it. What else are they if not hashmaps?
March 08, 2005
Ben Hinkle wrote:

>>I disagree. An out of bounds array index is an exceptional case because the size of the array is, usually, a known quantity - i.e. all members of the set of numbers from 0...n are valid, and n *must* be known during the allocation of the array. 
> 
> 
> Dynamic arrays grow and shrink all the time. Same thing with adding and removing
> keys from an AA. The only difference (conceptually) is that dynamic arrays have
> a continuous block of integer keys. But I don't see why that matters.

Maybe I'm missing something, but the only way in D for a dynamic array to grow or shrink is to set the length property, correct? That means the last index is always known - the index (n + 1) always points to an area of memory beyond the end of the array.

I said in another post that the [] used by associative arrays causes people to view them in the same light as normal arrays. From this perspective, it's easy to draw the conclusing that a aa["missing key"] is invalid and exceptional. But if D had a hashmap class instead, would hashmap.get("missing key") still be viewed as an exceptional case?
March 08, 2005
Mike Parker wrote:

> In my opinion, aas should function thusly:
> 
> boolean contains = (key in aa);
> int* val = aa["key"]; // return null if missing
> 
> I don't see a problem with using pointers as return values, as it eliminates the requirement that all aa values be objects, and pointers are a part of the language anyway.

And it would make more sense, than the current situation:

bool contains = cast(bool) (key in aa);
int* val = key in aa; // return null if missing

It's just that some people tend to hate pointers...

> Perhaps I'm wrong viewing associative rays in the same light as Java's Hashmaps. But in my mind it's a natural way to look at it. What else are they if not hashmaps?

Technically it does not have to be a Hash, but it is definitely a Map...

--anders