Thread overview
How do you check for nonempty string?
Apr 13, 2018
Dr.No
Apr 13, 2018
Adam D. Ruppe
Apr 13, 2018
user1234
Apr 13, 2018
Jonathan M Davis
April 13, 2018
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?
April 13, 2018
On Friday, 13 April 2018 at 17:38:39 UTC, Dr.No wrote:
>>string s = null;
>>if(s !is null && s[0] == '/')
>
> is this correct?

No, that doesn't work if the string = "a"[$..$] for example

Just use

if(s.length && s[0])

instead
April 13, 2018
On Friday, 13 April 2018 at 17:41:00 UTC, Adam D. Ruppe wrote:
> On Friday, 13 April 2018 at 17:38:39 UTC, Dr.No wrote:
>>>string s = null;
>>>if(s !is null && s[0] == '/')
>>
>> is this correct?
>
> No, that doesn't work if the string = "a"[$..$] for example
>
> Just use
>
> if(s.length && s[0])
>
> instead

just `if (s.length)` is enough.


April 13, 2018
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