On Friday, April 13, 2018 17:38:39 Dr.No via Digitalmars-d-learn wrote:
> s.length > 0 or s !is null?
>
> used to C++/C#'s world I cautch myself doing something like this:
> > if(s !is null && s.length > 0 && s[0] == '/)
>
> then a I remembered the D's way, which length is probably a
> function not a property (in the C++/C#'s sense, which needs this
> as first parameter, hence s.length with s being null would result
> in error).
>
> But it seems it's just enough:
> >string s = null;
> >if(s !is null && s[0] == '/')
>
> is this correct?

A dynamic array in D is essentially

struct DynamicArray(T)
{
    size_t length;
    T* ptr;
}

When you use ==, you're checking whether the two dynamic arrays are of the
same length and whether they're elements are equal with ==. Essentially, you
get something like

bool arrEqual(T)(T[] lhs, T[] rhs)
{
    if(lhs.length != rhs.length)
        return false;

    foreach(i; 0 .. lhs.length)
    {
        if(lhs[i] != rhs[i])
            return false;
    }

    return true;
}

though I'm fairly certain that it does so in a more optimized manner in at
least some cases. When you use is, you're checking whether the two dynamic
arrays are identical, essentially getting

bool arrIs(T)(T[] lhs, T[] rhs)
{
    return lhs.length is rhs.length && lhs.ptr is lhs.ptr;
}

So, the behavior you get is

assert([1, 2, 3, 4] == [1, 2, 3, 4]);
assert([1, 2, 3, 4] !is [1, 2, 3, 4]);

auto arr = [1, 2, 3, 4];
assert(arr == arr);
assert(arr is arr);

null is a dynamic array with length 0 and a null ptr. So, with null, you get

assert("" == null);
assert("" !is null);

You don't have to worry about null being dereferenced in either case,
because is never deferences ptr (it just needs to check the length and ptr
values for equality), and == won't bother looking at the elements if the
length is 0. You do have to worry about accessing elements that don't exist,
so something like arr[0] will throw a RangeError if the arr.length == 0, but
the value of ptr doesn't matter in that case, just the length.

So, if you want to check whether a dynamic array is really null, you need to
use is. On the other hand, if what you want to check is the length of the
dynamic array, then you can just check length. e.g.

if(str.length != 0)

or more idiomatically, you can use empty from std.range.primitives, e.g.

if(!str.empty)

but empty just returns str.length == 0. You technically could also do

if(str != null)

but it's not very idiomatic and anyone reading it would have to wonder
whether what you really meant was

if(str !is null)

which would be the correct way to check whether the string was null rather
than empty. As such, use == or != with null is a bit of a red flag. It
works, but the odds are high enough that the programmer just didn't
understand the differences between == and is and how null is treated as a
dynamic array that it really isn't good practice even if you do fully
understand the semantics.

If you're looking to check whether a string starts with a particular
character, you can do something like

if(!str.empty && str[0] == '/')

However, it's arguably cleaner and more idiomatic to take advantage of
std.algorithm.searching.startsWith

if(str.startsWith('/'))

which takes care of the null check for you. It also works with ranges in
general and not just dynamic arrays.

- Jonathan M Davis

Reply via email to