On Saturday, January 07, 2012 15:06:30 Ali Çehreli wrote:
> On 01/07/2012 02:11 PM, RenatoL wrote:
>  > Very quick question
>  > 
>  > import std.stdio;
>  > void main()
>  > {
>  > 
>  >    auto arr1 = ["uno":1, "due":2, "tre":3];
>  >    arr1.remove("xxx");
>  > 
>  > }
>  > 
>  > also in this case the compiler does not say anything and the
>  > program goes out silently ... why? Would not it be better if an
>  > exception was raised?
> 
> I think that could be a valid design choice. On the other hand, since
> what is required is to remove the element, it is not really an error if
> the object is already missing. The requirement is met.
> 
>  > After all if i write:
>  > 
>  > writeln(arr1["xxx"]);
>  > 
>  > runtime expresses its disappointment...
> 
> You get the exception more simply by this:
> 
>      auto e = arr1["xxx"];
> 
> But that's understandable because the [] operator is supposed to provide
> access to a usable object. Since there is no general concept of a null
> object, there is no object to provide access to, so there is nothing
> else to do but to throw.

You likely know this, but I'll point it out in case a newbie to decide to get 
htrowing behavior out of the substript operator.

If the element is not in the container, then the subscript operator throws a 
RangeError if -release isn't used, so it's an Error, not an Exception, and 
isn't a Throwable that you're supposed to catch (since the unwinding of the 
stack skips destructors, scope statements, finall blocks for any Throwables 
which aren't either Exception or derived from Exception). Also, without -
release, it does no bounds checking and will likely result in a segfault. So, 
relying on the subscript operator throwing is a _bad_ idea. The idea is that 
you never give it something that isn't actually in the container.

If you need to check it, and you're dealing with a dynamic or static array, 
then you check the array's length. If you're dealing with an associative 
array, then you use the in operator to get a pointer to the element from the 
container and check whether it's null or not (since if it's null, it wasn't 
there).

It would probably make remove more expensive if it had to throw when it didn't 
find an element, and for the most part, it's rather meaningless whether it was 
in the container before that. As pointed out, remove makes sure that the 
element is no longer in the container after it's been called. It has no real 
reason to care whether an element was in there before or not. And if _you_ 
don't care, then being forced to check whether an element was in the container 
before trying to remove it would make your code less efficient. The way remove 
is now, the check only occurs if you do it yourself and therefore actually 
_want_ it. And odds are, such a check would be an assertion anyway (and 
therefore would be throwing an AssertError on failure, not an Exception), 
since the fact that the element wasn't in there anymore is a bug in your code, 
since your code is assuming that it's there.

So, while I can understand someone's first reaction being why remove doesn't 
throw if the element isn't there, when you really think through it, it does 
make more sense for it not to throw.

- Jonathan M Davis

Reply via email to