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
|