Thread overview
Why do associative arrays throw an Error (RangeError) on value not found?
Dec 31, 2013
Supernova
Dec 31, 2013
Jacob Carlborg
Dec 31, 2013
John Colvin
Dec 31, 2013
bearophile
Dec 31, 2013
Jonathan M Davis
Dec 31, 2013
Meta
December 31, 2013
Why do associative arrays throw an Error (RangeError) on value not found?

This seems like it would be inefficient to check for, so a recoverable Exception (ItemNotFoundException?) would seem to be more appropriate.

Or is Array[Key] with a key that is not in the array and bounds checking disabled undefined behavior?
December 31, 2013
On 2013-12-31 13:42, Supernova wrote:
> Why do associative arrays throw an Error (RangeError) on value not found?
>
> This seems like it would be inefficient to check for, so a recoverable
> Exception (ItemNotFoundException?) would seem to be more appropriate.

How would ItemNotFoundException be any more efficient? The idea is that the error should not be recoverable. If you get an RangeError in your code you have made a logical error.

You need to explicitly check if a key is available in the associative array before accessing it, something like this:

if (auto value = key in aa)
    writefln("key %s was found with the value %s", key, value);

else
    writefln("key %s was not found", key);

-- 
/Jacob Carlborg
December 31, 2013
On Tuesday, 31 December 2013 at 12:55:59 UTC, Jacob Carlborg wrote:
> On 2013-12-31 13:42, Supernova wrote:
>> Why do associative arrays throw an Error (RangeError) on value not found?
>>
>> This seems like it would be inefficient to check for, so a recoverable
>> Exception (ItemNotFoundException?) would seem to be more appropriate.
>
> How would ItemNotFoundException be any more efficient? The idea is that the error should not be recoverable. If you get an RangeError in your code you have made a logical error.
>
> You need to explicitly check if a key is available in the associative array before accessing it, something like this:
>
> if (auto value = key in aa)
>     writefln("key %s was found with the value %s", key, value);
>
> else
>     writefln("key %s was not found", key);

Doesn't that duplicate the work of discovering whether the key is there or not? I guess it would depend on the implementation.
December 31, 2013
On Tuesday, 31 December 2013 at 12:42:33 UTC, Supernova wrote:
> Why do associative arrays throw an Error (RangeError) on value not found?
>
> This seems like it would be inefficient to check for, so a recoverable Exception (ItemNotFoundException?) would seem to be more appropriate.
>
> Or is Array[Key] with a key that is not in the array and bounds checking disabled undefined behavior?

It seems to me like it's more or less an artifact from earlier D, maybe even back to D1. It's possible that it was designed like that so AAs behave the same way on accessing a non-existent index as normal arrays, for simplicity I suppose (though anyone that's used an AA in another language would probably find this behaviour weird). Item not found is not really a logic error, and not really deserving of a RangeError (who wants their program to crash when something as simple as an AA lookup fails?), but it's not too hard to get around. You have both `value in AA`, which returns a pointer that's null if the value is not found, and `AA.get(value, default)`, which returns `default` if `value` is not found.
December 31, 2013
John Colvin:

> Doesn't that duplicate the work of discovering whether the key is there or not? I guess it would depend on the implementation.

If you compile the code with ldc2, the compiler in most cases is able to perform the associative array lookup only once. Elsewhere I suggested to add the same optimization to dmd.

With dmd currently you can avoid the double lookup manually because "key in aa" doesn't return a boolean as logic and good practice suggests, it returns a pointer that is null when the key is not found, and it points to the value when the key is present. So storing and dereferencing this pointer you can avoid the double lookup.

Bye,
bearophile
December 31, 2013
On Tuesday, December 31, 2013 13:39:25 John Colvin wrote:
> On Tuesday, 31 December 2013 at 12:55:59 UTC, Jacob Carlborg
> 
> wrote:
> > On 2013-12-31 13:42, Supernova wrote:
> >> Why do associative arrays throw an Error (RangeError) on value
> >> not found?
> >> 
> >> This seems like it would be inefficient to check for, so a
> >> recoverable
> >> Exception (ItemNotFoundException?) would seem to be more
> >> appropriate.
> > 
> > How would ItemNotFoundException be any more efficient? The idea is that the error should not be recoverable. If you get an RangeError in your code you have made a logical error.
> > 
> > You need to explicitly check if a key is available in the associative array before accessing it, something like this:
> > 
> > if (auto value = key in aa)
> > 
> >     writefln("key %s was found with the value %s", key, value);
> > 
> > else
> > 
> >     writefln("key %s was not found", key);
> 
> Doesn't that duplicate the work of discovering whether the key is there or not? I guess it would depend on the implementation.

Not really. If you don't know whether it's there or not, use the in operator. If you know that it's there, then use the subscript operator.

auto value = key in aa; //Maybe it's there, maybe not
auto value2 = aa[key2]; //It's definitely there and is a bug if it's not

You'd get a double lookup if the in operator returned a bool and then had to use the subscript operator to fetch it, but fortunately, in returns a pointer to the value (or null if it's not there), which is more efficient and a lot more useful.

- Jonathan M Davis