www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Reading about D: few questions

reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
Hi guys!

I'm mostly familiar with C (and a bit of PHP). I've stumbled upon the D 
language, and I must say I really like it.
Now I'm reading the "The D Programming Language" book, and I have a 
couple of questions:


1. Uninitialized Arrays and GC.

http://dlang.org/memory.html#uninitializedarrays
It's said here ^ that:
"The uninitialized data that is on the stack will get scanned by the 
garbage collector looking for any references to allocated memory."
With the given example of: byte[1024] buffer = void;

So does the GC really scan this byte array? Or (sounds more logical to 
me) does it scan only reference types?
If the latter is true, I think the example should use some kind of a 
pointer array. Also, in this case, I can't see why "Uninitialized data 
can be a source of bugs and trouble, even when used correctly."?
If the former is true, then, well, I'll ask more questions.


2. Setting Dynamic Array Length.

http://dlang.org/arrays.html#resize
"A more practical approach would be to minimize the number of resizes"

The solution works but is not as clean as just using array ~= c;
Is there any way (language, runtime, or phobos) to declare an array that 
would reallocate memory by chunks, which are multiple of x?


3. const and immutable.

Is there any use for const when defining variables?
As I see it, there is no use for using e.g. const int x;, as it can't be 
modified anyway;
So with immutable, const is only good for reference variables that are 
initialized to refer to another variable (like a function const ref 
parameter).
Am I right?


4. if (&lhs != &rhs)?

std.algorithm has this in it's swap function.
Is it different than if (lhs !is rhs)?
Just wondering.


5. Align attribute.

http://dlang.org/attribute.html#align

struct S {
   align(4) byte a; // placed at offset 0
   align(4) byte b; // placed at offset 1
}

Explain this please.


6. Array slices manipulation.

a[] += 1; works but a[]++ doesn't.
Not so important but just wondering: why, and is it intended?


7. Anonymous structs.
In C you can write:

struct { int a; } s = {10};
printf("%d\n", s.a);

In D you must declare the struct first:

struct S { int a; };
S s = {10};
writeln(s.a);

Why doesn't D allow anonymous structs?


Best regards.
Dec 23 2011
next sibling parent Mafi <mafi example.org> writes:
Am 23.12.2011 16:25, schrieb Mr. Anonymous:
 Hi guys!

 I'm mostly familiar with C (and a bit of PHP). I've stumbled upon the D
 language, and I must say I really like it.
 Now I'm reading the "The D Programming Language" book, and I have a
 couple of questions:
[....]
 3. const and immutable.

 Is there any use for const when defining variables?
 As I see it, there is no use for using e.g. const int x;, as it can't be
 modified anyway;
 So with immutable, const is only good for reference variables that are
 initialized to refer to another variable (like a function const ref
 parameter).
 Am I right?
Right. There's no point in a const int but of course there is a big difference between const(int)* and immutable(int)*.
 4. if (&lhs != &rhs)?

 std.algorithm has this in it's swap function.
 Is it different than if (lhs !is rhs)?
 Just wondering.
They're not the same at all. "is" checks if the two operands have binary equality. To understand, you have to keep in mind that lhs and rhs are references and could refer to one and the same variable as in: int a = 0; swap(a, a); Now, if you want to know if two refs refer to the same variable, you use &lhs == &rhs. If want to know if two class instances are the same, you use is. If you want to know if two things (instances or anything else) are equal, you use ==. &lhs == &rhs (makes only sense with refs) rhs is lhs (always true, if the above is true) rhs == lhs (always true, if the above is true) import std.stdio; void f(ref int[] a, ref int[] b) { writefln("%s %s %s", &a == &b, a is b, a == b); } void main() { auto u = [1, 2, 3]; auto u2 = u; auto v = [1, 2, 3]; auto w = [4, 5, 6]; f(u, u); // true true true f(u, u2);// false true true f(u, v); // false false true f(u, w); // false false false }
 [...]
Mafi
Dec 23 2011
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/23/2011 07:25 AM, Mr. Anonymous wrote:

 I have a couple of questions:
I prefer separate threads for each. :)
 1. Uninitialized Arrays and GC.

 http://dlang.org/memory.html#uninitializedarrays
 It's said here ^ that:
 "The uninitialized data that is on the stack will get scanned by the
 garbage collector looking for any references to allocated memory."
 With the given example of: byte[1024] buffer = void;

 So does the GC really scan this byte array? Or (sounds more logical to
 me) does it scan only reference types?
I am not an expert on garbage collectors but I've never heard about differentiating the bits of data. The GC would have to need to keep meta data about every part of the allocated space as such and it would not be practical.
 If the latter is true, I think the example should use some kind of a
 pointer array. Also, in this case, I can't see why "Uninitialized data
 can be a source of bugs and trouble, even when used correctly."?
I don't think that the last part is any different than the "initialize all of your variables" advice. The uninitialized data has come from memory that has been used earlier in the program and may have valid data (and references) to existing or already-destroyed data. Hard to debug.
 2. Setting Dynamic Array Length.

 http://dlang.org/arrays.html#resize
 "A more practical approach would be to minimize the number of resizes"

 The solution works but is not as clean as just using array ~= c;
 Is there any way (language, runtime, or phobos) to declare an array that
 would reallocate memory by chunks, which are multiple of x?
Array expansion is already more efficient than they look at first. This article is a good read: http://www.dsource.org/projects/dcollections/wiki/ArrayArticle
 3. const and immutable.

 Is there any use for const when defining variables?
 As I see it, there is no use for using e.g. const int x;, as it can't be
 modified anyway;
 So with immutable, const is only good for reference variables that are
 initialized to refer to another variable (like a function const ref
 parameter).
 Am I right?
Right. I have two observations myself: - To be more useful, function parameters should not insist on immutable data, yet we type string all over the place. - To be more useful, functions should not insist on the mutability of the data that they return. The following function makes a new string: char[] endWithDot(const(char)[] s) { return s ~ '.'; } char[] s; s ~= "hello"; auto a = endWithDot(s); It is good that the parameter is const(char) so that I could pass the mutable s to it. But the orthogonal problem of the type of the return is troubling. The result is clearly mutable yet it can't be returned as such: Error: cannot implicitly convert expression (s ~ '.') of type const(char)[] to char[] We've talked about this before. There is nothing in the language that makes me say "the returned object is unique; you can cast it to mutable or immutable freely."
 5. Align attribute.

 http://dlang.org/attribute.html#align

 struct S {
 align(4) byte a; // placed at offset 0
 align(4) byte b; // placed at offset 1
 }

 Explain this please.
I don't know more than what the documentation says but I remember reading bugs about align().
 6. Array slices manipulation.

 a[] += 1; works but a[]++ doesn't.
 Not so important but just wondering: why, and is it intended?
Again, I remember discussion and limitations about this feature. Fixed-length arrays have better support and the regular increment works: double[3] a = [ 10, 20, 30 ]; ++a[];
 7. Anonymous structs.
 In C you can write:

 struct { int a; } s = {10};
 printf("%d\n", s.a);

 In D you must declare the struct first:

 struct S { int a; };
 S s = {10};
 writeln(s.a);

 Why doesn't D allow anonymous structs?
It may be related to palsing. D does not require the semicolon at the end of the struct definition, so it wouldn't know what 's' is: struct { int a; } // definition (of unmentionable type :) ) s = {10}; // unknown s There could be special casing but I don't think that it would be worth it. Ali
Dec 23 2011
next sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 23.12.2011 19:47, Ali Çehreli wrote:
 On 12/23/2011 07:25 AM, Mr. Anonymous wrote:

  > I have a couple of questions:

 I prefer separate threads for each. :)
Should I resend the questions as separate messages?
  > 1. Uninitialized Arrays and GC.
  >
  > http://dlang.org/memory.html#uninitializedarrays
  > It's said here ^ that:
  > "The uninitialized data that is on the stack will get scanned by the
  > garbage collector looking for any references to allocated memory."
  > With the given example of: byte[1024] buffer = void;
  >
  > So does the GC really scan this byte array? Or (sounds more logical to
  > me) does it scan only reference types?

 I am not an expert on garbage collectors but I've never heard about
 differentiating the bits of data. The GC would have to need to keep meta
 data about every part of the allocated space as such and it would not be
 practical.
Maybe not every part, but only reference parts.
  > If the latter is true, I think the example should use some kind of a
  > pointer array. Also, in this case, I can't see why "Uninitialized data
  > can be a source of bugs and trouble, even when used correctly."?

 I don't think that the last part is any different than the "initialize
 all of your variables" advice. The uninitialized data has come from
 memory that has been used earlier in the program and may have valid data
 (and references) to existing or already-destroyed data. Hard to debug.

  > 2. Setting Dynamic Array Length.
  >
  > http://dlang.org/arrays.html#resize
  > "A more practical approach would be to minimize the number of resizes"
  >
  > The solution works but is not as clean as just using array ~= c;
  > Is there any way (language, runtime, or phobos) to declare an array that
  > would reallocate memory by chunks, which are multiple of x?

 Array expansion is already more efficient than they look at first. This
 article is a good read:

 http://www.dsource.org/projects/dcollections/wiki/ArrayArticle
Thanks, I'll take a look.
  > 3. const and immutable.
  >
  > Is there any use for const when defining variables?
  > As I see it, there is no use for using e.g. const int x;, as it can't be
  > modified anyway;
  > So with immutable, const is only good for reference variables that are
  > initialized to refer to another variable (like a function const ref
  > parameter).
  > Am I right?

 Right. I have two observations myself:

 - To be more useful, function parameters should not insist on immutable
 data, yet we type string all over the place.

 - To be more useful, functions should not insist on the mutability of
 the data that they return.

 The following function makes a new string:

 char[] endWithDot(const(char)[] s)
 {
 return s ~ '.';
 }

 char[] s;
 s ~= "hello";
 auto a = endWithDot(s);

 It is good that the parameter is const(char) so that I could pass the
 mutable s to it.

 But the orthogonal problem of the type of the return is troubling. The
 result is clearly mutable yet it can't be returned as such:

 Error: cannot implicitly convert expression (s ~ '.') of type
 const(char)[] to char[]

 We've talked about this before. There is nothing in the language that
 makes me say "the returned object is unique; you can cast it to mutable
 or immutable freely."
I saw that std.string functions use assumeUnique from std.exception. As for your example, it probably should be: char[] endWithDot(const(char)[] s) { return s.dup ~ '.'; }
  > 5. Align attribute.
  >
  > http://dlang.org/attribute.html#align
  >
  > struct S {
  > align(4) byte a; // placed at offset 0
  > align(4) byte b; // placed at offset 1
  > }
  >
  > Explain this please.

 I don't know more than what the documentation says but I remember
 reading bugs about align().

  > 6. Array slices manipulation.
  >
  > a[] += 1; works but a[]++ doesn't.
  > Not so important but just wondering: why, and is it intended?

 Again, I remember discussion and limitations about this feature.
 Fixed-length arrays have better support and the regular increment works:

 double[3] a = [ 10, 20, 30 ];
 ++a[];
++a[] works, but a[]++ doesn't.
  > 7. Anonymous structs.
  > In C you can write:
  >
  > struct { int a; } s = {10};
  > printf("%d\n", s.a);
  >
  > In D you must declare the struct first:
  >
  > struct S { int a; };
  > S s = {10};
  > writeln(s.a);
  >
  > Why doesn't D allow anonymous structs?

 It may be related to palsing. D does not require the semicolon at the
 end of the struct definition, so it wouldn't know what 's' is:

 struct { int a; } // definition (of unmentionable type :) )
 s = {10}; // unknown s

 There could be special casing but I don't think that it would be worth it.
Sounds reasonable.
 Ali
Dec 23 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 23, 2011 20:19:28 Mr. Anonymous wrote:
 I saw that std.string functions use assumeUnique from std.exception.
 As for your example, it probably should be:
 
 char[] endWithDot(const(char)[] s)
 {
      return s.dup ~ '.';
 }
No, that allocates _two_ strings - one from dup and one as the result of the concatenation. It should either be auto retval = s.dup; retval ~= '.'; return retval; or return cast(char[])(s ~ '.'); The problem is that because s is const(char)[], the result of the concatenation is that type. But it's guaranteed to be a new string, so the cast is fine. It's arguably better to use the first version though, since it doesn't require a cast. - Jonathan M Davis
Dec 23 2011
prev sibling next sibling parent "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 23.12.2011 19:47, Ali Çehreli wrote:
 On 12/23/2011 07:25 AM, Mr. Anonymous wrote:
  > 2. Setting Dynamic Array Length.
  >
  > http://dlang.org/arrays.html#resize
  > "A more practical approach would be to minimize the number of resizes"
  >
  > The solution works but is not as clean as just using array ~= c;
  > Is there any way (language, runtime, or phobos) to declare an array that
  > would reallocate memory by chunks, which are multiple of x?

 Array expansion is already more efficient than they look at first. This
 article is a good read:

 http://www.dsource.org/projects/dcollections/wiki/ArrayArticle
std.array.Appender is what I was talking about :)
Dec 23 2011
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 23, 2011 09:47:35 Ali =C3=87ehreli wrote:
 - To be more useful, function parameters should not insist on immutab=
le
 data, yet we type string all over the place.
That depends. If they're going to have to idup the data anyway, then it= 's=20 better to require that the argument be immutable so that that cost is c= lear.=20 The worst is taking const and then iduping, because then you're forced = to idup=20 strings which didn't need to be iduped. And in general, operating on strings is more efficient than mutable cha= racter=20 arrays, because you can slice them with impunity, whereas you often hav= e to=20 dup or idup mutable arrays in order to avoid altering the original data= . The=20 area where the immutability becomes problematic is when you actually wa= nt to=20 directly mutate a string - but that's generally a rather iffy thing to = do with=20 UTF-8 anyway, since you have to deal with the varying length of the var= ious=20 code points within the string. That being said, an increasing number of functions in Phobos are templa= ted on=20 string type so that you can use whatever string type that you want with= them.=20 And there is a push (at least with toString) to add the ability to put = the=20 result of a string function into an existing string of some variety (be= it=20 using a delegate or an output range). So, you'll be forced to use strin= g less,=20 but the reality of the matter is that in the general case you should pr= obably=20 be using string anyway (there are, of course, always exceptions).
 - To be more useful, functions should not insist on the mutability of=
 the data that they return.

 The following function makes a new string:
=20
 char[] endWithDot(const(char)[] s)
 {
      return s ~ '.';
 }
=20
      char[] s;
      s ~=3D "hello";
      auto a =3D endWithDot(s);
=20
 It is good that the parameter is const(char) so that I could pass the=
 mutable s to it.
=20
 But the orthogonal problem of the type of the return is troubling. Th=
e
 result is clearly mutable yet it can't be returned as such:
=20
 Error: cannot implicitly convert expression (s ~ '.') of type
 const(char)[] to char[]
=20
 We've talked about this before. There is nothing in the language that=
 makes me say "the returned object is unique; you can cast it to mutab=
le
 or immutable freely."
In general, D doesn't have features where the programmer says that some= thing=20 is okay. It's too interested in making guarantees for that. Either it c= an=20 guarantee something, or you force it with a cast. I can't think of even= one=20 feature where you say that _you_ guarantee that something is okay. Cast= ing is=20 your only option. That being said, the language is improving in what it can guarantee and= in=20 what it can do thanks to those guarantees. For instance, if you have a = pure=20 function and the compiler can guarantee that the return value doesn't=20= reference anything in the argumetns passed in, then the return value is= =20 implicitly convertible to whatever const-ness you want. If you want to be making such guarantees yourself, then what you typica= lly=20 have to do is templatize the function and take advantage of static if a= nd D's=20 compile-time reflection capabilities. Phobos does this quite a bit to i= mprove=20 performance and avoid having to duplicate data. Your particular example is quite easily fixed though. The issue is that= the=20 string which was passed in is typed as const(char)[], and the expressio= n s ~=20 '.' naturally results in the same type. But it's quite clear that the=20= resulting string could be of any constness, since it's a new string. So= , just=20 tell it what constness to have by casting it. - Jonathan M Davis
Dec 23 2011
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/23/2011 03:16 PM, Jonathan M Davis wrote:
 On Friday, December 23, 2011 09:47:35 Ali Çehreli wrote:
 - To be more useful, function parameters should not insist on immutable
 data, yet we type string all over the place.
That depends. If they're going to have to idup the data anyway, then it's better to require that the argument be immutable so that that cost is
clear.
 The worst is taking const and then iduping, because then you're 
forced to idup
 strings which didn't need to be iduped.
That would be leaking an implementation detail to the user. Besides, it doesn't solve the problem if the user is in the middle: void user(const(char)[] p) { writeln(endWithDot(p)); } The user itself would be forced to take immutable, but this time the reason is different: not because he is passing a copy optimization of its own, but because he is passing endWithDot()'s copy optimization to its caller. immutable would have to be leaked all the way up just because a low level function decided to make a copy! Perhaps the guideline should be: Everybody should take by immutable references so that this leaking of immutable through all layers should not be a problem in case a low-level function decided to make a copy.
 And in general, operating on strings is more efficient than mutable 
character
 arrays, because you can slice them with impunity, whereas you often 
have to
 dup or idup mutable arrays in order to avoid altering the original data.
Agreed. But immutable on the parameter list is an insistence: The function insists that the data be immutable. Why? Because it is going to store it for later use? Perhaps share it between threads? It is understandable when there is such a legitimate reason. Then the caller would see the reason too: "oh, takes immutable; that means my data may be used later as is."
 That being said, an increasing number of functions in Phobos are 
templated on
 string type so that you can use whatever string type that you want 
with them.
 And there is a push (at least with toString) to add the ability to 
put the
 result of a string function into an existing string of some variety 
(be it
 using a delegate or an output range). So, you'll be forced to use 
string less, Good. Ranges are more and more becoming "thinking in D." Perhaps we should be talking about a range that appends a dot at the end of the existing elements.
 but the reality of the matter is that in the general case you should 
probably
 be using string anyway (there are, of course, always exceptions).
I am looking for simple guidelines when designing functions. It is simple in C++: take data by reference to const if you are not going to modify it. (It is questionable whether small structs should be passed by value instead, but that's beside the point.) In C++, passing by reference to const works because the function accepts any type of mutability and a copy is avoided because it's a reference. In D, immutable is not more const than const (which was my initial assumption); it is an additional requirement: give me data that should never change. My point is that this requirement makes sense only in rare cases. Why would a function like endWithDot() insist on how mutable the user's data is?
 - To be more useful, functions should not insist on the mutability of
 the data that they return.

 The following function makes a new string:

 char[] endWithDot(const(char)[] s)
 {
       return s ~ '.';
 }

       char[] s;
       s ~= "hello";
       auto a = endWithDot(s);

 It is good that the parameter is const(char) so that I could pass the
 mutable s to it.

 But the orthogonal problem of the type of the return is troubling. The
 result is clearly mutable yet it can't be returned as such:

 Error: cannot implicitly convert expression (s ~ '.') of type
 const(char)[] to char[]

 We've talked about this before. There is nothing in the language that
 makes me say "the returned object is unique; you can cast it to mutable
 or immutable freely."
In general, D doesn't have features where the programmer says that
something
 is okay. It's too interested in making guarantees for that. Either it can
 guarantee something, or you force it with a cast. I can't think of 
even one
 feature where you say that _you_ guarantee that something is okay. 
Casting is
 your only option. [...]
I know. I used the wrong words. Yes, the compiler should see what I see: the returned object is unique and can be elevated to any mutability level.
 Your particular example is quite easily fixed though. The issue is 
that the
 string which was passed in is typed as const(char)[], and the 
expression s ~
 '.' naturally results in the same type. But it's quite clear that the
 resulting string could be of any constness, since it's a new string. 
So, just
 tell it what constness to have by casting it.
That's the other side of the problem: Why would the function dictate how the caller should treat this piece of data? The function should not arbitrarily put const or immutable on the data. That would be making it less useful. The data is mutable anyway. inout doesn't solve this problem as it is a connection between the mutability of the parameter(s) and the result. The mutability type of the result has nothing to do with the parameters' in the case of functions like endWithDot(). As you say, maybe the situation will get better in D and functions will simply return char[] and the compiler will convert it to automatically. I remembered that I had shown UniqueMutable when we discussed this issue last time: import std.stdio; import std.exception; struct UniqueMutable(T) { T data; bool is_used; this(ref T data) { this.is_used = false; this.data = data; data = null; } T as_mutable() { return as_impl!(T)(); } immutable(T) as_immutable() { return as_impl!(immutable(T))(); } private ConvT as_impl(ConvT)() { enforce(!is_used); ConvT result = cast(ConvT)(data); data = null; is_used = true; return result; } } UniqueMutable!T unique_mutable(T)(ref T data) { return UniqueMutable!T(data); } UniqueMutable!(char[]) foo() { char[] result = "hello".dup; result ~= " world"; return unique_mutable(result); } void main() { char[] mutable_result = foo().as_mutable; mutable_result[0] = 'H'; string immutable_result = foo().as_immutable; }
 - Jonathan M Davis
Ali
Dec 23 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
The core problem for a number of these situations is how types are handled 
with regards to expressions. In an expression such as

char[] arr = s ~ '.';

the type of the value being assigned is determined _before_ the assignment is 
done. So, even though in theory the compiler could make it work, it doesn't, 
because by the time it's looking at the type being assigned to, it's too late. 
There would need to be a fundamental change in how the language functions in 
order to fix issues like this.

pure can do it when it can not because it's able to look at what the return 
type is and changing the result of the expression accordingly but because it 
has guarantees which make it so that it knows that the return value could be 
converted to any level of constness and still be valid. The types used in the 
expressions internally are generally irrelevant.

So, while I completely agree that it would be an improvement if the compiler 
did a better job with implicit conversion when it could theoretically be done, 
I'm not sure how much of that we're actually going to end up seeing simply 
because of how the language and type system works in terms of the order of 
evaluation.

- Jonathan M Davis
Dec 23 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/24/2011 02:02 AM, Jonathan M Davis wrote:
 The core problem for a number of these situations is how types are handled
 with regards to expressions. In an expression such as

 char[] arr = s ~ '.';

 the type of the value being assigned is determined _before_ the assignment is
 done. So, even though in theory the compiler could make it work, it doesn't,
 because by the time it's looking at the type being assigned to, it's too late.
 There would need to be a fundamental change in how the language functions in
 order to fix issues like this.
Examples of resolved issues like this: int[] foo()pure; immutable(int)[] x = foo;
 pure can do it when it can not because it's able to look at what the return
 type is and changing the result of the expression accordingly but because it
 has guarantees which make it so that it knows that the return value could be
 converted to any level of constness and still be valid. The types used in the
 expressions internally are generally irrelevant.

 So, while I completely agree that it would be an improvement if the compiler
 did a better job with implicit conversion when it could theoretically be done,
 I'm not sure how much of that we're actually going to end up seeing simply
 because of how the language and type system works in terms of the order of
 evaluation.

 - Jonathan M Davis
I don't think this is very hard to get working.
Dec 24 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Mr. Anonymous:

 With the given example of: byte[1024] buffer = void;
 
 So does the GC really scan this byte array?
The current D GC is not precise, so I think the current DMD+GC scan this array. Future better compilers/runtimes probably will be able to avoid it (with a shadow stack the gives precise typing information at runtime, used by a precise GC).
 The solution works but is not as clean as just using array ~= c;
 Is there any way (language, runtime, or phobos) to declare an array that 
 would reallocate memory by chunks, which are multiple of x?
Appending to built-in D arrays is several times slower than doing the same thing to a C++ vector, but in many situations the performance is enough. When it's not enough there is the "capacity" function in the object module. Or for even better performance the appender in std.array, that gives performance just a little worse than the C++ vector push back.
 Is there any use for const when defining variables?
 As I see it, there is no use for using e.g. const int x;, as it can't be 
 modified anyway;
const int x = 5 + foo(y) * bax(z); It's better to use immutable or const everywhere this is possible and doesn't give you too many problems. In my D2 code about 70-90% of variables are now const or better immutable. This avoids some bugs and will help future compilers optimize code better.
 5. Align attribute.
 
 http://dlang.org/attribute.html#align
 
 struct S {
    align(4) byte a; // placed at offset 0
    align(4) byte b; // placed at offset 1
 }
 
 Explain this please.
I don't know. Keep in mind that DMD has many bugs, almost 50-100 gets removed every month.
 6. Array slices manipulation.
 
 a[] += 1; works but a[]++ doesn't.
 Not so important but just wondering: why, and is it intended?
It's a compiler bug. I think it's already in Bugzilla (but take a look in Bugzilla if you want to be sure).
 7. Anonymous structs.
 In C you can write:
 
 struct { int a; } s = {10};
 printf("%d\n", s.a);
 
 In D you must declare the struct first:
 
 struct S { int a; };
 S s = {10};
 writeln(s.a);
 
 Why doesn't D allow anonymous structs?
D doesn't allow top-level anonymous structs.
 ++a[] works, but a[]++ doesn't.
Already known compiler bug. ---------------------------- Ali:
There is nothing in the language that makes me say "the returned object is
unique; you can cast it to mutable or immutable freely."<
The return value of strongly pure functions is implicitly castable to immutable. And sometimes inout helps. Bye, bearophile
Dec 23 2011
next sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 23.12.2011 21:51, bearophile wrote:
 Mr. Anonymous:

 http://dlang.org/memory.html#uninitializedarrays
 It's said here ^ that:
 "The uninitialized data that is on the stack will get scanned by the
 garbage collector looking for any references to allocated memory."
 With the given example of: byte[1024] buffer = void;

 So does the GC really scan this byte array? Or (sounds more logical to
 me) does it scan only reference types?
 If the latter is true, I think the example should use some kind of a
 pointer array. Also, in this case, I can't see why "Uninitialized data
 can be a source of bugs and trouble, even when used correctly."?
 If the former is true, then, well, I'll ask more questions.
The current D GC is not precise, so I think the current DMD+GC scan this array. Future better compilers/runtimes probably will be able to avoid it (with a shadow stack the gives precise typing information at runtime, used by a precise GC).
Well, if that's really so, then it's not 100% reliable. e.g. you generate an array of random numbers, and one of them appears to be an address of an allocated array. This array won't free even if not used anymore.
Dec 23 2011
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/23/2011 12:36 PM, Mr. Anonymous wrote:
 On 23.12.2011 21:51, bearophile wrote:
 The current D GC is not precise, so I think the current DMD+GC scan
 this array. Future better compilers/runtimes probably will be able to
 avoid it (with a shadow stack the gives precise typing information at
 runtime, used by a precise GC).
Well, if that's really so, then it's not 100% reliable. e.g. you generate an array of random numbers, and one of them appears to be an address of an allocated array. This array won't free even if not used anymore.
I think it's the other way around: whatever this array seems to be referring to will not be freed until this array is freed. These are good examples of why uninitialized arrays are not for every application. There is also the option of allocating the memory directly from the GC: int * a = cast(int*)GC.calloc(100, GC.BlkAttr.NO_SCAN); (Some with GC.malloc()). Now we can fill that array with any value without the fear of having been mistaken for references. Ali
Dec 23 2011
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/23/2011 02:46 PM, Ali Çehreli wrote:
 On 12/23/2011 12:36 PM, Mr. Anonymous wrote:
  > you generate an array of random numbers, and one of them appears to
  > be an address of an allocated array. This array won't free even if not
  > used anymore.
OK, I misread what you said. I thought you were filling the array with random numbers. You are right. Ali
Dec 23 2011
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/23/2011 11:51 AM, bearophile wrote:

 Ali:

 There is nothing in the language that makes me say "the returned 
object is unique; you can cast it to mutable or immutable freely."<
 The return value of strongly pure functions is implicitly castable to 
immutable. Is that working yet? The commented-out lines below don't compile with 2.057: void main() { char[] s = "hello".dup; char[] am = endWithDot(s); const(char)[] ac = endWithDot(s); const(char[]) acc = endWithDot(s); // immutable(char)[] ai = endWithDot(s); // immutable(char[]) aii = endWithDot(s); } pure char[] endWithDot(const(char)[] s) { char[] result = s.dup; result ~= '.'; return result; } Also note that I could not use the better line below in endWithDot(): return s ~ '.'; as the type of the result is const(char)[]. I insist that it too should be castable to any mutable or immutable type.
 And sometimes inout helps.
Yes but it is only when the types of the parameters and the result should be related.
 Bye,
 bearophile
Ali
Dec 23 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 23, 2011 14:51:21 Ali =C3=87ehreli wrote:
 On 12/23/2011 11:51 AM, bearophile wrote:
  > Ali:
  >> There is nothing in the language that makes me say "the returned
=20
 object is unique; you can cast it to mutable or immutable freely."<
=20
  > The return value of strongly pure functions is implicitly castable=
to
=20
 immutable.
=20
 Is that working yet? The commented-out lines below don't compile with=
2.057:
=20
 void main()
 {
      char[] s =3D "hello".dup;
=20
      char[]            am  =3D endWithDot(s);
      const(char)[]     ac  =3D endWithDot(s);
      const(char[])     acc =3D endWithDot(s);
      // immutable(char)[] ai  =3D endWithDot(s);
      // immutable(char[]) aii =3D endWithDot(s);
 }
=20
 pure char[] endWithDot(const(char)[] s)
 {
      char[] result =3D s.dup;
      result ~=3D '.';
      return result;
 }
Well, that's not strongly pure - only weakly pure - so if the optimizat= ion is=20 only for strongly pure functions, then that won't work. I know that it = _could_=20 be done with weakly pure functions as well (such as your example here),= but=20 I'm not exactly sure what it does right now. The feature is new, so it = doesn't=20 yet work in all of the cases that it should, and it's not entirely clea= r=20 exactly far it will go. IIRC, Daniel Murphy and Steven were discussing = it a=20 while back, and it clearly didn't do as much as it could, and it wasn't= =20 entirely clear that it ever would beacuse of the increased complication= s=20 involved. However, it wil almost certainly work in more cases in the fu= ture=20 than it does now as the feature is improved. - Jonathan M Davis
Dec 23 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 The feature is new, so it doesn't 
 yet work in all of the cases that it should, and it's not entirely clear 
 exactly far it will go. IIRC, Daniel Murphy and Steven were discussing it a 
 while back,
I have very recently opened another thread about it, but unfortunately it didn't attract a lot of attention: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=153041
 and it wasn't 
 entirely clear that it ever would beacuse of the increased complications 
 involved.
Yeah. -------------------- Ali:
      return s ~ '.';
 
 as the type of the result is const(char)[]. I insist that it too should
 be castable to any mutable or immutable type.
Add a request in Bugzilla if it's not already present. I don't know how much complex it is to implement in the compiler. Bye, bearophile
Dec 23 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, December 23, 2011 14:51:06 bearophile wrote:
 And sometimes inout helps.
Yeah, good point. I keep forgetting about inout, since it didn't work properly before. So, the best way to implement Ali's function would be inout(char)[] endWithDot(inout(char)[] s) { return s ~ '.'; } - Jonathan M Davis
Dec 23 2011
prev sibling parent reply Denis Shelomovskij <verylonglogin.reg gmail.com> writes:
23.12.2011 22:51, bearophile ïèøåò:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Dec 24 2011
next sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile ïèøåò:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
Dec 24 2011
parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
2011/12/24 Mr. Anonymous <mailnew4ster gmail.com>:
 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/ar=
raybyte.d#L1127
 But `a[]++` should store a copy of `a`, increment elements and return
 stored copy. It is hidden GC allocation. We already have a silent
 allocation in closures, but here a _really large_ peace of data can be
 allocated. Yes, this allocation sometimes can be optimized out but not
 always.

 IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig =3D a++; int[] arr_orig =3D arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Dec 24 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/24/2011 06:18 PM, Andrew Wiley wrote:
 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:
 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); }
Dec 24 2011
parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:
 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link =
to
 one of these epic comments (even x100 more epic because of '%' use



 https://github.com/D-Programming-Language/druntime/blob/master/src/rt/=
arraybyte.d#L1127
 But `a[]++` should store a copy of `a`, increment elements and return
 stored copy. It is hidden GC allocation. We already have a silent
 allocation in closures, but here a _really large_ peace of data can be
 allocated. Yes, this allocation sometimes can be optimized out but not
 always.

 IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig =3D a++; int[] arr_orig =3D arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ =C2=A0 =C2=A0int payload; =C2=A0 =C2=A0D opUnary(string op:"++")(){payload++; return this;} } void main() { =C2=A0 =C2=A0D d =3D new D; =C2=A0 =C2=A0assert(d.payload =3D=3D 0); =C2=A0 =C2=A0assert(d++.payload =3D=3D 1); }
That doesn't match integer semantics: int a =3D 0; assert(a++ =3D=3D 0); assert(a =3D=3D 1);
Dec 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:
 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); }
That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1);
Yes, that was my point.
Dec 24 2011
parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch> =C2=A0wro=
te:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:

 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Lin=
k
 to
 one of these epic comments (even x100 more epic because of '%' use




 https://github.com/D-Programming-Language/druntime/blob/master/src/r=
t/arraybyte.d#L1127
 But `a[]++` should store a copy of `a`, increment elements and retur=
n
 stored copy. It is hidden GC allocation. We already have a silent
 allocation in closures, but here a _really large_ peace of data can =
be
 allocated. Yes, this allocation sometimes can be optimized out but n=
ot
 always.

 IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig =3D a++; int[] arr_orig =3D arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ =C2=A0 =C2=A0int payload; =C2=A0 =C2=A0D opUnary(string op:"++")(){payload++; return this;} } void main() { =C2=A0 =C2=A0D d =3D new D; =C2=A0 =C2=A0assert(d.payload =3D=3D 0); =C2=A0 =C2=A0assert(d++.payload =3D=3D 1); }
That doesn't match integer semantics: int a =3D 0; assert(a++ =3D=3D 0); assert(a =3D=3D 1);
Yes, that was my point.
Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a +=3D 1' do not have such ambiguities.
Dec 24 2011
next sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 24.12.2011 21:22, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch>    wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:

 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); }
That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1);
Yes, that was my point.
Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a += 1' do not have such ambiguities.
Maybe you're right, but a[]++; alone, imo, should compile.
Dec 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/24/2011 08:41 PM, Mr. Anonymous wrote:
 On 24.12.2011 21:22, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehr<timon.gehr gmx.ch> wrote:
 On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch> wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:

 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); }
That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1);
Yes, that was my point.
Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a += 1' do not have such ambiguities.
Maybe you're right, but a[]++; alone, imo, should compile.
+1.
Dec 24 2011
parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, Dec 24, 2011 at 1:45 PM, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 12/24/2011 08:41 PM, Mr. Anonymous wrote:
 On 24.12.2011 21:22, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehr<timon.gehr gmx.ch> wrote:
 On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch> wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:

 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile =D0=BF=D0=B8=D1=88=D0=B5=D1=82:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons t=
o
 generate x2-x100 faster code without any compiler optimisations.
 Link
 to
 one of these epic comments (even x100 more epic because of '%' us=
e





 https://github.com/D-Programming-Language/druntime/blob/master/sr=
c/rt/arraybyte.d#L1127
 But `a[]++` should store a copy of `a`, increment elements and
 return
 stored copy. It is hidden GC allocation. We already have a silent
 allocation in closures, but here a _really large_ peace of data
 can be
 allocated. Yes, this allocation sometimes can be optimized out
 but not
 always.

 IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig =3D a++; int[] arr_orig =3D arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and ar=
r
 must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d =3D new D; assert(d.payload =3D=3D 0); assert(d++.payload =3D=3D 1); }
That doesn't match integer semantics: int a =3D 0; assert(a++ =3D=3D 0); assert(a =3D=3D 1);
Yes, that was my point.
Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array. I guess it could be argued that since arrays have hybrid value/reference semantics, no copy should be made and the original should change. Actually, looking at it from that angle, a[]++ is fundamentally ambiguous because it could have value semantics or reference semantics, so I would argue that we shouldn't have it for that reason. '++a' and 'a +=3D 1' do not have such ambiguities.
Maybe you're right, but a[]++; alone, imo, should compile.
+1.
You could special case this, but I'd be happy with an error that told you to use one of the working alternatives.
Dec 24 2011
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/24/2011 08:22 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 1:08 PM, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 12/24/2011 07:00 PM, Andrew Wiley wrote:
 On Sat, Dec 24, 2011 at 9:50 AM, Timon Gehr<timon.gehr gmx.ch>    wrote:
 On 12/24/2011 06:18 PM, Andrew Wiley wrote:

 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:

 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Not necessarily. class D{ int payload; D opUnary(string op:"++")(){payload++; return this;} } void main() { D d = new D; assert(d.payload == 0); assert(d++.payload == 1); }
That doesn't match integer semantics: int a = 0; assert(a++ == 0); assert(a == 1);
Yes, that was my point.
Then I'm not understanding what you're trying to prove. I'm saying that if we implement a postfix ++ operator for arrays, keeping the language consistent would require it to make a copy if the user stores a copy of the original array.
And I said: "not necessarily" That is because reference types have had semantics that go well with not making a copy all along, so there is no danger of making things more inconsistent.
 I guess it could be argued
 that since arrays have hybrid value/reference semantics, no copy
 should be made and the original should change.

 Actually, looking at it from that angle, a[]++ is fundamentally
 ambiguous because it could have value semantics or reference
 semantics, so I would argue that we shouldn't have it for that reason.
 '++a' and 'a += 1' do not have such ambiguities.
I don't think a[]++ should necessarily be there either.
Dec 24 2011
prev sibling parent reply "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 24.12.2011 19:18, Andrew Wiley wrote:
 2011/12/24 Mr. Anonymous<mailnew4ster gmail.com>:
 On 24.12.2011 19:01, Denis Shelomovskij wrote:
 23.12.2011 22:51, bearophile пишет:
 ++a[] works, but a[]++ doesn't.
Already known compiler bug.
Is it a joke? Array expression in D are for performance reasons to generate x2-x100 faster code without any compiler optimisations. Link to one of these epic comments (even x100 more epic because of '%' use https://github.com/D-Programming-Language/druntime/blob/master/src/rt/arraybyte.d#L1127 But `a[]++` should store a copy of `a`, increment elements and return stored copy. It is hidden GC allocation. We already have a silent allocation in closures, but here a _really large_ peace of data can be allocated. Yes, this allocation sometimes can be optimized out but not always. IMHO, D should not have `a[]++` operator.
Why should it store a copy? o_O I also don't see any allocations in the code on the URL above.
int a_orig = a++; int[] arr_orig = arr[]++; If ++ is going to be applied to an array, it needs to have the same meaning as it does elsewhere. After this operation, arr_orig and arr must refer to different arrays for that to be true.
Actually, when I think of it: int a_orig = a++; int[] arr_orig = arr[]++; Should be read as: int a_orig = a; ++a; int[] arr_orig = arr[]; ++arr[]; (If I'm not mistaken, it was written in the TDPL book) Which means no copy of arr is made, and both arrays (which reference to the same block) are affected.
Dec 24 2011
parent reply Denis Shelomovskij <verylonglogin.reg gmail.com> writes:
25.12.2011 0:48, Mr. Anonymous пишет:
 Actually, when I think of it:

 int a_orig = a++;
 int[] arr_orig = arr[]++;

 Should be read as:

 int a_orig = a;
 ++a;
 int[] arr_orig = arr[];
 ++arr[];

 (If I'm not mistaken, it was written in the TDPL book)

 Which means no copy of arr is made, and both arrays (which reference to
 the same block) are affected.
OK. As I wrote: "Yes, this allocation sometimes can be optimized out but not always.". Consider this: --- void main() { int[] a = new int[5]; void f(int[] b) { // Here we assume that b is unchanged a. // As these array differ we need a copy. assert(b[0] == 0); assert(a[0] == 1); } f(a[]++); // Note: compilation error now } --- Why not to rewrite `f(a[]++);` as `f(a); ++a[];`? Because postincrement is expected to increment its argument when it is executed. It just returns an unchanged copy. Analogous D code with integers illustrates this: --- void main() { int a; void f(int b) { assert(b == 0); assert(a == 1); } f(a++); } ---
Dec 25 2011
parent "Mr. Anonymous" <mailnew4ster gmail.com> writes:
On 25.12.2011 11:28, Denis Shelomovskij wrote:
 OK. As I wrote: "Yes, this allocation sometimes can be optimized out but
 not always.". Consider this:
 ---
 void main()
 {
 int[] a = new int[5];
 void f(int[] b)
 {
 // Here we assume that b is unchanged a.
 // As these array differ we need a copy.
 assert(b[0] == 0);
 assert(a[0] == 1);
 }
 f(a[]++); // Note: compilation error now
 }
 ---
 Why not to rewrite `f(a[]++);` as `f(a); ++a[];`? Because postincrement
 is expected to increment its argument when it is executed. It just
 returns an unchanged copy. Analogous D code with integers illustrates this:
 ---
 void main()
 {
 int a;
 void f(int b)
 {
 assert(b == 0);
 assert(a == 1);
 }
 f(a++);
 }
 ---
I wasn't familiar with this postincrement behavior. I would expect both a and b to be 0 inside f(). Anyway, what do you suggest? To leave it not compilable? My original point was to just allow: a[]++; More complicated scenarios like the one above is beyond my knowledge, as I'm only learning the language, but I think they have to be addressed as well.
Dec 29 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Denis Shelomovskij:

 IMHO, D should not have `a[]++` operator.
I see, and sorry. (Those percentage comments are relative to tests done on large arrays, so they are silly.) Bye, bearophile
Dec 24 2011
prev sibling parent Trass3r <un known.com> writes:
 5. Align attribute.

 http://dlang.org/attribute.html#align

 struct S {
    align(4) byte a; // placed at offset 0
    align(4) byte b; // placed at offset 1
 }

 Explain this please.
align is a huge mess imo. "It matches the corresponding C compiler behavior" So what's the point of align in the first place, if the compiler does what it wants anyway, see above? The only thing that really works is align(1) struct S {...} for packed structs.
Dec 23 2011