www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why do associative arrays throw an Error (RangeError) on value not

reply "Supernova" <supernova2003dh yahoo.com> writes:
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?
Dec 31 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Dec 31 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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.
Dec 31 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Dec 31 2013
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 31 2013
prev sibling parent "Meta" <jared771 gmail.com> writes:
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.
Dec 31 2013