What about putting array.empty in object.d?
Jonathan M Davis
jmdavisProg at gmx.com
Wed Mar 21 14:15:44 PDT 2012
On Wednesday, March 21, 2012 15:46:12 Steven Schveighoffer wrote:
> On Wed, 21 Mar 2012 14:33:58 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
>
> wrote:
> > On Wednesday, March 21, 2012 15:54:51 Daniel Murphy wrote:
> >> FWIW, I would rather see `if (array)` translated to `if (array.length)`
> >> and
> >> this become the recomended way to check if an array is empty. Wouldn't
> >> that
> >> remove the dependency on std.array for most of the cases?
> >
> > The problem with checking whether length == 0 is that it's inefficient
> > for some
> > containers, so it's generally good practice to use empty rather than
> > length.
>
> But we are specifically talking about arrays, not containers in general.
> Containers in general are not defined by the language.
I know that. Much point is that length == 0 is a bad thing to do in general,
because it's ineffecient with some containers. The language itself is pretty
much irrelevant as far as that goes. As such, I'd argue in pretty much _any_
language that using length == 0 instead of empty is _not_ a good habit to be
in. Doing it with arrays will make it much more likely that you'll end up
doing it with containers without thinking about it. On the other hand, if
you're in the habit of _always_ using empty rather than length == 0, then you
don't have the problem.
> > And while length == 0 is fine for arrays, it promotes bad habits in
> > general, so
> > I'm against it and think that code should pretty much always use empty
> > rather
> > than length == 0.
>
> I think you may misunderstand the proposal. if(array) translating to
> if(array.length) is *only* for arrays, not for general types.
No. I understand just fine. My point is that doing length == 0 for _any_ type
of container is bad, because it promotes bad habits and leads to inefficient
code for containers where it _does_ matter. So, I'd argue that if you should
always be using empty rather than length == 0 - even with arrays - which
currently means that you're almost always importing std.array. Having empty in
object.d certainly isn't necessary, but it mitigates the problem, because then
you don't have to import it if all you care about is empty.
if(array) is a special case. If we want to change it to translate to
if(array.length) then fine. That's all tied up in the insanity of an empty
array and a null array being considered equal. But even if you want to use
that syntax, it only mitigates the length == 0 vs empty issue for arrays
rather than eliminating, because it only works directly in if statements and
the like. The issue of choosing length == 0 vs empty still remains in many
cases.
And actually, I'd personally shy away from the if(array) syntax regardless
simply because of the inherent ambiguity. Even if the language clearly defines
it, I believe that it's the sort of thing that programmers are likely to
misunderstand - particularly since if(var) checks for null with all of the
other reference types. Experienced D programmers will know, but since newbies
probably won't I'd consider it a code smell.
I think that muddling null and empty was D's largest mistake with arrays and
tend to think that any code that isn't explicit about it is asking for trouble
if nothing else because the odds aren't low that the programmer did one thing
when they meant another, because they didn't understand how null and empty
arrays interact (e.g. arr == null is _always_ a bad sign IMHO).
> I don't see why defining empty in object.d is necessary for things that
> don't involve ranges at all.
It's not necessary, but it would be nice. empty isn't just a range thing.
Containers in general use it (across many languages whether ranges are
involved or not), and for the reasons that I've already given, I don't think
that length == 0 should ever be used in code. So I'd argue that you should
always be using empty, which means importing std.array all the time if empty
isn't in object.d, even if you _aren't_ doing range-based operations.
Now, range-based operations are so common that you pretty much have to import
std.range in most code anyway, so it really isn't all that much of a burden to
have to import std.array or std.range to get at empty, but putting it in
object.d definitely provides some benefit.
So, I'm not sure that I care all that much whether std.array.empty gets moved
to object.d or not, but I'd strongly argue that code should import std.array
and use it rather than checking length == 0 as long as empty is in std.array
rather than in object.d. So, if putting empty in object.d promotes the use of
empty over length == 0, I'm all for it.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list