Thread overview
Is an automatic string variable a dynamic array in the sense of sec. 10.11.2 "Identity Expression" par. 4?
Jul 15, 2022
kdevel
Jul 15, 2022
ag0aep6g
Jul 15, 2022
Salih Dincer
Jul 16, 2022
Mathias LANG
Jul 16, 2022
Dukc
Jul 17, 2022
kdevel
Jul 19, 2022
Quirin Schroll
July 15, 2022

The rule [1] states:

For [...] dynamic arrays, identity is defined as referring to the same
array elements and the same number of elements.

[BTW: Every two arrays having the same elements implies that they also have the same number of elements. Hence the second condition is redundant.]

In this piece of code [2]:

   void main ()
   {
      string s = null;
      string t = "";
      assert (s is t);
   }

the assertion trips although both conditions of the given rule are met.

The second condition of the rule is true: Both arrays have the same number of elements (zero). For the first condition to be false it requires an index position at which the elements of both arrays differ. Since there is no such position the first condition is not false, meaning it is also true.

Therefor the documentation does not document the actual behavior of D implementations (checked dmd and gdc). The issue is not restricted to the string type.

[1] https://dlang.org/spec/expression.html#identity_expressions
[2] https://issues.dlang.org/show_bug.cgi?id=17623

July 15, 2022

On Friday, 15 July 2022 at 13:34:03 UTC, kdevel wrote:

>

The rule [1] states:

For [...] dynamic arrays, identity is defined as referring to the same
array elements and the same number of elements.

[BTW: Every two arrays having the same elements implies that they also have the same number of elements. Hence the second condition is redundant.]

"Referring to the same array elements" is supposed to mean that the .ptr is the same. Maybe the phrasing can be improved.

July 15, 2022

On Friday, 15 July 2022 at 13:34:03 UTC, kdevel wrote:

>

In this piece of code [2]:

   void main ()
   {
      string s = null;
      string t = "";
      assert (s is t);
   }

the assertion trips although both conditions of the given rule are met.

      string s, t;
void main()
{
      assert(s is t);
      assert(s is null);
      assert(t is null);

      s.length = 2;
      t.length = 2;

      assert(!is(s == t)); // true (check identy)
      assert(s == t); // true (check content)

      // because they are different strings:
      assert(is(string : typeof(s)));
      assert(is(string : typeof(t)));

      // but it can be same:
      auto u = s[0..2]; // a dynamic array

      assert(s is u); // true
      assert(s == u); // right on

      import std.stdio; // see following:
      writeln(cast(ubyte[])s); // [255, 255]
      writeln(cast(ubyte[])t); // [255, 255]
      writeln(cast(ubyte[])u); // [255, 255]

SDB%79

July 16, 2022

On Friday, 15 July 2022 at 13:34:03 UTC, kdevel wrote:

>

the assertion trips although both conditions of the given rule are met.

Another way to express is would be to say: their immediate value are binary equivalent. For value type it's simple (it also means that float.init is float.init but not all NaN will be equal obviously), but for reference type, it's just comparing their pointer (and for arrays, their length).

Note that there is a very subtle difference between null and "", and it matters.
null means .ptr is null && .length == 0 while "" means .ptr !is null && .length == 0.

This is crazy, right ? Well no, it's on purpose, because string literals have a \0 past their end, to ensure compatibility with C (something we had overwhelming evidence of being a good thing). So the "subtle difference" is that assert("".ptr + 1 == 0);.

July 16, 2022

On Saturday, 16 July 2022 at 13:03:42 UTC, Mathias LANG wrote:

>

So the "subtle difference" is that assert("".ptr + 1 == 0);.

You mean assert("".ptr[0] == 0), right?

July 17, 2022

On Saturday, 16 July 2022 at 13:03:42 UTC, Mathias LANG wrote:

>

On Friday, 15 July 2022 at 13:34:03 UTC, kdevel wrote:

>

the assertion trips although both conditions of the given rule are met.

Another way to express is would be to say [...]

I only want to point out that the current documentation does not document the actual behavior. Meanwhile I proposed an corrected statement in the bugzilla issue. And I am fully aware what is going on in the engine room. Thanks for your participation anyway.

July 19, 2022

On Saturday, 16 July 2022 at 13:03:42 UTC, Mathias LANG wrote:

>

Another way to express is would be to say: their immediate value are binary equivalent. For value type it's simple (it also means that float.init is float.init but not all NaN will be equal obviously), but for reference type, it's just comparing their pointer (and for arrays, their length).

I wouldn’t use the term “binary equivalent”. It sounds… wrong – and I’ll tell you why. We’re in precise-definition territory. Here, “equivalent” is not the same as “equal”. If I’m not horribly mistaken, the is operator for value types plainly compares the bytes, that is, the bytes are equal. I could imagine a definition for “binary equivalent” that is different from “binary equal”: Padding bits are ignored and if the struct has internal pointers, those point to the same offset, respectively. Of course, that is a vague term, as “equivalent” usually is in contrast to “equal”.