www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - null == "" is true?

reply Antonio <antonio abrevia.net> writes:
It works

```d
void main()
{
    assert(null=="");
}
```

why?
Jul 12 2022
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Jul 12, 2022 at 04:27:44PM +0000, Antonio via Digitalmars-d-learn wrote:
 It works
 
 ```d
 void main()
 {
    assert(null=="");
 }
 ```
 
 why?
Because an empty string is, by default, represented by an empty slice of the null pointer. Do not rely on this, however; it's possible sometimes to get an empty string that isn't null, e.g., if you incrementally shrink a slice over a string until it's empty. In that case, .ptr will not be null, but the string will still be empty. Always compare strings against "" rather than null, because the latter may not do what you think it does sometimes. T -- One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"
Jul 12 2022
next sibling parent Hipreme <msnmancini hotmail.com> writes:
On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
 On Tue, Jul 12, 2022 at 04:27:44PM +0000, Antonio via 
 Digitalmars-d-learn wrote:
 It works
 
 ```d
 void main()
 {
    assert(null=="");
 }
 ```
 
 why?
Because an empty string is, by default, represented by an empty slice of the null pointer. Do not rely on this, however; it's possible sometimes to get an empty string that isn't null, e.g., if you incrementally shrink a slice over a string until it's empty. In that case, .ptr will not be null, but the string will still be empty. Always compare strings against "" rather than null, because the latter may not do what you think it does sometimes. T
Yup, always compare the string with "". I have had this kind of problem a bunch of times, comparing it with null but it is not actually null
Jul 12 2022
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/12/22 12:40 PM, H. S. Teoh wrote:
 Because an empty string is, by default, represented by an empty slice of
 the null pointer.
No, it's not a null pointer. It's a pointer to a zero-character. But it is indeed an empty slice. -Steve
Jul 12 2022
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
 Because an empty string is, by default, represented by an empty 
 slice of the null pointer.

 Do not rely on this, however; it's possible sometimes to get an 
 empty string that isn't null, e.g., if you incrementally shrink 
 a slice over a string until it's empty. In that case, .ptr will 
 not be null, but the string will still be empty.  Always 
 compare strings against "" rather than null, because the latter 
 may not do what you think it does sometimes.
This is actually 100% reliable when comparing with the `==` operator because two empty strings always compare equal with `==`, regardless of what they point to. string s = "hello"; string empty1 = s[0 .. 0]; string empty2 = s[1 .. 1]; assert(empty1 == null); assert(empty2 == null); assert(empty1 == empty2); The real problem is that `s == null` looks like it does one thing (test for a null pointer) while actually doing something slightly different (test for an empty string).
Jul 12 2022
parent reply Antonio <antonio abrevia.net> writes:
On Tuesday, 12 July 2022 at 18:56:43 UTC, Paul Backus wrote:
 On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
 Because an empty string is, by default, represented by an 
 empty slice of the null pointer.

 Do not rely on this, however; it's possible sometimes to get 
 an empty string that isn't null, e.g., if you incrementally 
 shrink a slice over a string until it's empty. In that case, 
 .ptr will not be null, but the string will still be empty.  
 Always compare strings against "" rather than null, because 
 the latter may not do what you think it does sometimes.
This is actually 100% reliable when comparing with the `==` operator because two empty strings always compare equal with `==`, regardless of what they point to. string s = "hello"; string empty1 = s[0 .. 0]; string empty2 = s[1 .. 1]; assert(empty1 == null); assert(empty2 == null); assert(empty1 == empty2); The real problem is that `s == null` looks like it does one thing (test for a null pointer) while actually doing something slightly different (test for an empty string).
Then: ```d string a = null; assert(a is null); assert(a == ""); string b = ""); assert(b !is null); assert(b == ""); ``` Honestly, it is difficult to understand for newcomers... there is a reason, but there is a reason in javascript for `0 == ''` too
Jul 12 2022
next sibling parent Antonio <antonio abrevia.net> writes:
On Tuesday, 12 July 2022 at 20:36:03 UTC, Antonio wrote:
 Honestly, it is difficult to understand for newcomers... there 
 is a reason, but there is a reason in javascript for `0 == ''` 
 too
Correction ```d string a = null; assert(a is null); assert(a == ""); string b = ""; assert(b !is null); assert(b == null); ```
Jul 12 2022
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/12/22 4:36 PM, Antonio wrote:
 On Tuesday, 12 July 2022 at 18:56:43 UTC, Paul Backus wrote:
 On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
 Because an empty string is, by default, represented by an empty slice 
 of the null pointer.

 Do not rely on this, however; it's possible sometimes to get an empty 
 string that isn't null, e.g., if you incrementally shrink a slice 
 over a string until it's empty. In that case, .ptr will not be null, 
 but the string will still be empty. Always compare strings against "" 
 rather than null, because the latter may not do what you think it 
 does sometimes.
This is actually 100% reliable when comparing with the `==` operator because two empty strings always compare equal with `==`, regardless of what they point to.     string s = "hello";     string empty1 = s[0 .. 0];     string empty2 = s[1 .. 1];     assert(empty1 == null);     assert(empty2 == null);     assert(empty1 == empty2); The real problem is that `s == null` looks like it does one thing (test for a null pointer) while actually doing something slightly different (test for an empty string).
Then: ```d string a = null; assert(a is null); assert(a == ""); string b = ""); assert(b !is null); assert(b == null); ``` Honestly, it is difficult to understand for newcomers... there is a reason, but there is a reason in javascript for `0 == ''` too
It's not just for `null`. And it's unrelated to what javascript is doing. ```d string a = "abcabc"; assert(a[0 .. 3] == a[3 .. $]) assert(a[0 .. 3] !is a[3 .. $]) ``` The point is, `==` compares *value*, `is` always compares *identity*. And you cannot override `is`, it must always be predictable. For arrays, of course, you can't override `==`, but custom types can. -Steve
Jul 12 2022
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 12 July 2022 at 22:58:32 UTC, Steven Schveighoffer 
wrote:
 ```d
 string a = "abcabc";
 assert(a[0 .. 3] ==  a[3 .. $])
 assert(a[0 .. 3] !is a[3 .. $])
 ```

 The point is, `==` compares *value*, `is` always compares 
 *identity*.
Consider null type array which is a related topic but it cannot get a null element! The first is ok, but the second is legal. So no effect, is it normal? ```d auto p = [ null, null ];//* assert( is(typeof(null)[] : typeof(p) ) ); /* and it has two(2) elements */ p ~= null; // okay assert(p.length == 3); // true p ~= []; // legal (no error) assert(p.length != 4); // what! (no effect) assert(p[0] == []); // true assert([] == null); // right on import std.stdio; typeid(p).write(": ", p.length); writeln("->", []); // typeof(null)[]: 3->[] ``` SDB 79
Jul 14 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Friday, 15 July 2022 at 06:38:58 UTC, Salih Dincer wrote:
 Consider null type array which is a related topic but it cannot 
 get a null element!  The first is ok, but the second is legal. 
 So no effect, is it normal?

 ```d
 auto p = [ null, null ];//*
   assert(
     is(typeof(null)[] :
        typeof(p)
     )
   ); /* and it has two(2) elements */

   p ~= null;             // okay
   assert(p.length == 3); // true

   p ~= [];               // legal (no error)
   assert(p.length != 4); // what! (no effect)

   assert(p[0] == []);    // true
   assert([] == null);    // right on

   import std.stdio;
   typeid(p).write(": ", p.length);
   writeln("->", []); // typeof(null)[]: 3->[]
 ```
Yes, this is expected. Note that the term `null` and `[]` are special tokens that morph type to whatever is most appropriate at the time. `null` implicitly can be typed as any pointer type, or any array type. `[]` can be typed as any array type. However, it can't be implicitly typed as `typeof(null)`, which is a special unit type. ```d typeof(null) x; x = []; // error; ``` So consider that appending an *element type* to an array increases the array size, whereas appending an *array type* to an array adds the elements of the latter to the former. In this case, zero elements. There are still some inconsistencies though: ```d pragma(msg, typeof([])); // void[], likely to avoid breaking code. void[][] arr; arr ~= []; // does not append an element int[] x = [1, 2]; int[] y = null; // ok, null implicitly converts to any array x ~= y; // ok, no elements added x ~= null; // error, does not consider the implicit conversion to int[] ``` -Steve
Jul 15 2022
parent Salih Dincer <salihdb hotmail.com> writes:
On Friday, 15 July 2022 at 11:12:07 UTC, Steven Schveighoffer 
wrote:
 Note that the term `null` and `[]` are special tokens that 
 morph type to whatever is most appropriate at the time. `null` 
 implicitly can be typed as any pointer type, or any array type. 
 `[]` can be typed as any array type. However, it can't be 
 implicitly typed as `typeof(null)`, which is a special unit 
 type.
Thank you. I didn't know what to do with a null array though? I think void[] would be more useful. SDB 79
Jul 15 2022
prev sibling parent reply Kagamin <spam here.lot> writes:
On Tuesday, 12 July 2022 at 20:36:03 UTC, Antonio wrote:
 Honestly, it is difficult to understand for newcomers... there 
 is a reason, but there is a reason in javascript for `0 == ''` 
 too
People would have different preferences there. Difference between null and empty is useless. D does the right thing here, what other languages do, is a mistake. If you want such difference, use the Nullable wrapper or Algebraic.
Jul 18 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 18 July 2022 at 17:20:04 UTC, Kagamin wrote:
 Difference between null and empty is useless.
Not really. `null` typically means that the value is missing, irrelevant and not usable, which is quite different from having "" as a usable value.
Jul 18 2022
prev sibling parent reply Antonio <antonio abrevia.net> writes:
On Monday, 18 July 2022 at 17:20:04 UTC, Kagamin wrote:
 ... If you want such difference, use the Nullable wrapper or 
 Algebraic.
I do :-) In fact, I use algebraic types supporting Null and Undefined for DTOs representation (and REST APIs). But I discovered some "rare" side effects in libraries like vibe.d and structs where, sometimes, am empty string is deserialized as null (value is null) and I have to assume that null in an string is always "" for avoiding this weird effects I'm under pressure to meet deadlines and a team that is telling me "Why D instead typescript, Antonio?"... One month ago I reported some questions in forums or git repos... but I have to finish my work and 2 hours stoppers are not acceptable now. I will study it in detail and report (if required). May be, I will write the DTO problem with D article if I find time in august.
Jul 18 2022
parent reply Kagamin <spam here.lot> writes:
On Monday, 18 July 2022 at 21:23:32 UTC, Antonio wrote:
 I will study it in detail and report (if required). May be, I 
 will write the DTO problem with D article if I find time in 
 august.
In my experience null and empty in DTOs usually play the same logical role. It's a very contrived technical difference without practical usage, such distinction is way beyond any business logic. Even if you implement this distinction, I'm not sure anybody will carefully pay attention to it. In languages that make difference between null and empty, null is often replaced with empty to work around problems with null, such codebase can't properly preserve null values.
Jul 19 2022
parent reply Antonio <antonio abrevia.net> writes:
On Tuesday, 19 July 2022 at 08:10:25 UTC, Kagamin wrote:
 On Monday, 18 July 2022 at 21:23:32 UTC, Antonio wrote:
 I will study it in detail and report (if required). May be, I 
 will write the DTO problem with D article if I find time in 
 august.
In my experience null and empty in DTOs usually play the same logical role. It's a very contrived technical difference without practical usage, such distinction is way beyond any business logic. Even if you implement this distinction, I'm not sure anybody will carefully pay attention to it. In languages that make difference between null and empty, null is often replaced with empty to work around problems with null, such codebase can't properly preserve null values.
When you have to "patch" information partially (i.e.: update only the name and the phonenumber, but not the birthdate) or you must return in a REST partial information (because graphql or custom REST) there is only 2 ways to represent this "possible missing properties" * Maps (key->value) or similiar (i.e.:JSon objects): You can include or not keys in the map: If you don't want to update the birthdate, don't include the birthdate key in the DTO. * Structs (or any kind of structured data that can be validated at compile time): There is no possibility to say that some properties of the struct can be not present... Well, you can if you begin to manage Algebraic Types (Union types): `height: int | undefined` NULL is not the same that UNDEFINED The distintion is really important: NULL is a valid value (i.e.: The person phonenumber is NULL in database)... Of course, you can represent this concept natively in you language (Nullable, Optional, Maybe ...) but it is not the same that UNDEFINED... because UNDFINED says "This property has not been assigned to DTO... do not take it into account". The summary is that a DTO that works like a Map needs to represent the absent key ant this is not the same that the Null value Example: ```d struct Null { /*...*/ } struct Undefined { /*...*/ } struct ContactDto { DtoVal!(Undefined, string) name DtoVal!(Undefined, Null, string) phonenumber, DtoVal!(Undefined, AddressDto) address } // ... ContactDto data = {phonenumber:Null(), address:{city:{code:"BCN"}}}; updateContact(id, data); ```
Jul 19 2022
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 19 July 2022 at 10:29:40 UTC, Antonio wrote:
 NULL is not the same that UNDEFINED

 The distintion is really important:  NULL is a valid value 
 (i.e.: The person phonenumber is NULL in database)... Of 
 course, you can represent this concept natively in you language 
 (Nullable, Optional, Maybe ...) but it is not the same that 
 UNDEFINED... because UNDFINED says "This property has not been 
 assigned to DTO... do not take it into account".
IIRC someone wrote a master thesis about the different roles for null values in databases and came up with many different null situations (was it five?). E.g. for floating point you have two different types of not-a-number, one for representing a conversion failure/corruption of a datafield and another one for representing a computational result that cannot be represented. If we consider zero to be "empty" then floating point has four different "empty" values (+0, -0, qNaN, sNaN).
Jul 19 2022
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
On Tuesday, 19 July 2022 at 10:29:40 UTC, Antonio wrote:
 The summary is that a DTO that works like a Map needs to 
 represent the absent key ant this is not the same that the Null 
 value

 Example:
 ```d
 struct Null { /*...*/ }
 struct Undefined { /*...*/ }
 struct ContactDto {
  DtoVal!(Undefined, string) name
  DtoVal!(Undefined, Null, string) phonenumber,
  DtoVal!(Undefined, AddressDto) address
 }
 // ...
 ContactDto data = {phonenumber:Null(), 
 address:{city:{code:"BCN"}}};
 updateContact(id, data);

 ```
As I understand, in your scenario there's no difference between null string and empty string, they both work like empty string, and D treats them as empty string. That's what I mean when I said that distinction between null and empty is meaningless.
Jul 19 2022
parent Antonio <antonio abrevia.net> writes:
On Tuesday, 19 July 2022 at 16:55:39 UTC, Kagamin wrote:
 As I understand, in your scenario there's no difference between 
 null string and empty string, they both work like empty string, 
 and D treats them as empty string. That's what I mean when I 
 said that distinction between null and empty is meaningless.
Sorry Kagamin... I dindn't read this comment and I added a very large answer to the next one that has no sense :-p. I miss being able to delete answers from the forum :-) **Yes... I decided to treat the same way internally** for strings. Previously * `DtoVal!(Null, string)( null)` was equivalent to `DtoVal!(Null,string)( Null() )` * `DtoVal!(Null, Person)( null)` was equivalent to `DtoVal!(Null,string)( Null() )` Currently * `DtoVal!(Null, string)( null )` is equivalent to `DtoVal!(Null,string)( "" )`; * For other types this will raise a runtime exception: `DtoVal!(Null, Person)( null )`. * The correct way of is `DtoVal!(Null, Person)( Null() )` Basically, **`null` is completely useless and out of my code** with the exception of strings. Best regards Antonio
Jul 20 2022
prev sibling parent reply Kagamin <spam here.lot> writes:
Also what's the difference between null and empty phone number?
Jul 19 2022
parent reply Antonio <antonio abrevia.net> writes:
On Tuesday, 19 July 2022 at 17:05:27 UTC, Kagamin wrote:
 Also what's the difference between null and empty phone number?
In a relational database, `NULL` is not the same that `""`... and `NULL` is not the same that `0`. Are semantically different and there are database invariants (like foreign keys) based on it. Trying to "mix" this concepts in a database is a mistake. When you treat with Domain Models, you try to represent this semantics in all levels of your software... including APIs If your address has not a reference to the city... then there is a `city_code` field with `NULL` value in your database and the Address model object has a city property representing this Null value with the tools that language/library offers to you: `Nullable!City` or `Sumtype!(Null, City)` or `Optional<City>` or ...). `Null` is then a valid value state that has nothing related to *`null` pointers*... to avoid confusion, I talk about `Null` instead `null`. I, personally, prefer to use Union types (algebraic types) like `int | Null | ...` because it is the best option to introduce the Undefined state (that allows statically typed data to represent the absence of a property). `Sumtype!(Undefined,Null,int)` instead `Optional!(Nullable!int)` Then there is the `match!` syntax, the unified way to treat JSON serialization and the easy way to implement a custom "dot" accessor that propagates the Null or Undefined state in a chain of references: ```d person.ns.address.ns.city.ns.name.match!( (string name){ ... } (Null) {...} (Undefined) { ... } ) ```
Jul 19 2022
parent reply Kagamin <spam here.lot> writes:
On Tuesday, 19 July 2022 at 18:05:34 UTC, Antonio wrote:
 In a relational database, `NULL` is not the same that `""`... 
 and `NULL` is not the same that `0`.  Are semantically 
 different and there are database invariants (like foreign keys) 
 based on it.   Trying to "mix" this concepts in a database is a 
 mistake.
So, it's an implementation detail or a relational database that leaks into business logic because nobody thought about it? Just because a relational database has many features, it doesn't mean business logic must use them all, it must use only what makes sense for business logic.
 When you treat with Domain Models, you try to represent this 
 semantics in all levels of your software... including APIs
What semantics your domain models implement? Is it semantics of all features of a relational database or is semantics of business logic?
Jul 20 2022
parent Antonio <antonio abrevia.net> writes:
On Wednesday, 20 July 2022 at 13:35:14 UTC, Kagamin wrote:
 On Tuesday, 19 July 2022 at 18:05:34 UTC, Antonio wrote:
 In a relational database, `NULL` is not the same that `""`... 
 and `NULL` is not the same that `0`.  Are semantically 
 different and there are database invariants (like foreign 
 keys) based on it.   Trying to "mix" this concepts in a 
 database is a mistake.
So, it's an implementation detail or a relational database that leaks into business logic because nobody thought about it? Just because a relational database has many features, it doesn't mean business logic must use them all, it must use only what makes sense for business logic.
It is not about "so many fetaures"... it is about entity model and how relational database stores it. General purpose programming languages include their own representation to the NULL concept that is not "relational model" dependent: Optional, Maybe, Nullable, Union types
 What semantics your domain models implement? Is it semantics of 
 all features of a relational database or is semantics of 
 business logic?
Database is an **strict repository**: it stores the entity model with relational semantics including strict invariant management (primary keys, foreign keys, field types, nullablility, ...) and following normalization rules (3th normal form, at least). It is, basically, a "consistent" model. Business logic **trust on database repository invariants** and implements whatever your Business Model require (i.e.: complex model operations involving multiple repository operations). Business works using Objects/Entities of the domain and it is required a way to map this to relational model (ORM or manual SQL)... Usually in a specific "Data" or "DAO" layer. Transactions are your friend (The only way to ensure that high level invariants are enforced) If you can't be confident with database invariants (because you are using NoSQL repository like MongoDB or DynamoDB or an Old ISAM MySQL or "trash" models over relational engine) then you need to "move" all these "consistency" control to the business layer developing workflows/processes that must be ready to work with "inconsistent" data... (You can read this article I wrote 2 years ago about SQL/NoSQL solutions and Brewer's conjecture: https://qr.ae/pvklQA) Business "architecture" based on a single repository is the simplest one... But the pleasure of trusting on a relational database is always welcome.
Jul 20 2022
prev sibling next sibling parent reply user1234 <user1234 12.de> writes:
On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
 On Tue, Jul 12, 2022 at 04:27:44PM +0000, Antonio via 
 Digitalmars-d-learn wrote:
 It works
 
 ```d
 void main()
 {
    assert(null=="");
 }
 ```
 
 why?
Because an empty string is, by default, represented by an empty slice of the null pointer. Do not rely on this, however;
Absolutely. I'd like to add: especially as default parameter value that's an array. Never use null. use `[]` (empty array literal).
Jul 12 2022
parent reply ag0aep6g <anonymous example.com> writes:
On Tuesday, 12 July 2022 at 19:02:01 UTC, user1234 wrote:
 On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
[...]
 Do not rely on this, however;
Absolutely. I'd like to add: especially as default parameter value that's an array. Never use null. use `[]` (empty array literal).
Just to be clear: `[]` and `null` are the exact same thing (null pointer, zero length). The reason to prefer `[]` over `null` is purely for readability. The meaning is exactly the same.
Jul 12 2022
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Jul 12, 2022 at 07:55:46PM +0000, ag0aep6g via Digitalmars-d-learn
wrote:
 On Tuesday, 12 July 2022 at 19:02:01 UTC, user1234 wrote:
 On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
[...]
 Do not rely on this, however;
Absolutely. I'd like to add: especially as default parameter value that's an array. Never use null. use `[]` (empty array literal).
Just to be clear: `[]` and `null` are the exact same thing (null pointer, zero length). The reason to prefer `[]` over `null` is purely for readability. The meaning is exactly the same.
Pedantically, no, they're not the same. You can assign null to a pointer, but you can't assign [] to a pointer. `null` is a supertype of `[]`. But probably nobody actually cares about this distinction. :-D T -- By understanding a machine-oriented language, the programmer will tend to use a much more efficient method; it is much closer to reality. -- D. Knuth
Jul 12 2022
parent ag0aep6g <anonymous example.com> writes:
On 12.07.22 22:14, H. S. Teoh wrote:
 Pedantically, no, they're not the same. You can assign null to a
 pointer, but you can't assign [] to a pointer. `null` is a supertype of
 `[]`.
 
 But probably nobody actually cares about this distinction. :-D
If we're ignoring context, "null" has four characters, while "[]" has only two. Clearly, they're not similar at all. The context was arrays, not pointers. `void f(T[] a = null) {}` has exactly the same meaning as `void f(T[] a = []) {}`.
Jul 12 2022
prev sibling parent user1234 <user1234 12.de> writes:
On Tuesday, 12 July 2022 at 19:55:46 UTC, ag0aep6g wrote:
 On Tuesday, 12 July 2022 at 19:02:01 UTC, user1234 wrote:
 On Tuesday, 12 July 2022 at 16:40:38 UTC, H. S. Teoh wrote:
[...]
 Do not rely on this, however;
Absolutely. I'd like to add: especially as default parameter value that's an array. Never use null. use `[]` (empty array literal).
Just to be clear: `[]` and `null` are the exact same thing (null pointer, zero length). The reason to prefer `[]` over `null` is purely for readability. The meaning is exactly the same.
ah yes. The case I thought to was actually ```d void test1(string s = null) { assert(s is null); } void test2(string s = "") // s is null term'ed, i.e not null { assert(s is null); } void main() { test1(); test2(); // fails } ``` the rule of thumb is to use `stuff.length` as condition, always, and not `stuff` itself, to prevent natyx, hard to find bugs.
Jul 12 2022
prev sibling parent reply Bienlein <ffm2002 web.de> writes:
 why?
Because an empty string is, by default, represented by an empty slice of the null pointer.
I don't program in D. I just read from time to time posts in the D forum because of the good quality of what people write. So, I'm not proficient in D, but in general internals should not boil up to the surface.
 In my experience null and empty in DTOs usually play the same 
 logical role.
Oh, oh ...
IIRC someone wrote a master thesis about the different roles for 
null values in databases >and came up with many different null 
situations (was it five?).
Oh, oh, oh ... I once worked on a system where some little robot running on a track picked up material in carriers from some machine and then brought it to the next machine. If the destination of a carrier was set to null, it implied that the destination was currently undefined. Then the robot brought the carrier to some rack where it was put aside for a while till the planning system had created a new production plan. The number of null pointer exceptions we had to fix because auf this was countless. Never make null imply some meaning ...
Jul 19 2022
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 19 July 2022 at 15:30:30 UTC, Bienlein wrote:
 If the destination of a carrier was set to null, it implied 
 that the destination was currently undefined. Then the robot 
 brought the carrier to some rack where it was put aside for a 
 while till the planning system had created a new production 
 plan. The number of null pointer exceptions we had to fix 
 because auf this was countless. Never make null imply some 
 meaning ...
This is due to a lack of proper abstractions. Null always has a meaning, if it didn't, you would not need it. In this particular case you could have used a singleton instead. In a relational database you can choose between having null or having a large number of tables. The latter performs poorly. I am not talking about how to implement null, I am talking about the concept of information being absent. If you have to represent that, you have a defacto "null", doesn't matter if it is a singleton or address zero or NaN or FFFE (for unicode).
Jul 19 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/12/22 12:27 PM, Antonio wrote:
 It works
 
 ```d
 void main()
 {
     assert(null=="");
 }
 ```
 
 why?
A string is not exactly a reference type. It's a length and a pointer. This can be confusing to newcomers, especially ones that come from languages that treat arrays and strings as object references. `null` as an array with `0` length and `null` pointer. `""` is an array with `0` length and a pointer to a zero character (not `null`). The algorithm to compare *any* arrays is first verify the lengths are the same. Then for each element in the array, compare them. Since there are 0 elements in both the empty string and the null string, they are equal. -Steve
Jul 12 2022
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 7/12/22 10:11, Steven Schveighoffer wrote:

 The algorithm to compare *any* arrays is first verify the lengths are
 the same. Then for each element in the array, compare them. Since there
 are 0 elements in both the empty string and the null string, they are
 equal.
Checking .empty() covered all of my uses cases. I think... :) void foo(string s) { import std.array; assert(s.empty); } void main() { // Literal null foo(null); // Zero-length and pointing at '\0' foo(""); // Fresh string a; foo(a); // Shrunk string b = "hello"; b.length = 0; assert(b.ptr !is null); foo(b); } Ali
Jul 12 2022
prev sibling parent Palak <plksharma481 gmail.com> writes:
Hi  Steven Schveighoffer,
Yes solution looking useful and sure it will work.

Thanks.
Jul 14 2022