www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why is this allowed

reply JN <666total wp.pl> writes:
Spent some time debugging because I didn't notice it at first, 
essentially something like this:

int[3] foo = [1, 2, 3];
foo = 5;
writeln(foo);   // 5, 5, 5

Why does such code compile? I don't think this should be 
permitted, because it's easy to make a mistake (when you wanted 
foo[index] but forgot the []). If someone wants to assign a value 
to every element they could do foo[] = 5; instead which is 
explicit.
Jun 30 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jun 30, 2020 at 04:22:57PM +0000, JN via Digitalmars-d-learn wrote:
 Spent some time debugging because I didn't notice it at first,
 essentially something like this:
 
 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5
 
 Why does such code compile? I don't think this should be permitted,
 because it's easy to make a mistake (when you wanted foo[index] but
 forgot the []).  If someone wants to assign a value to every element
 they could do foo[] = 5; instead which is explicit.
File a bug? I suspect that one potential reason is that nasty misfeature of static arrays implicitly converting to a slice of itself, so `foo = 5;` is in some sense being translated as `foo[] = 5;`. (And on that note, this implicit static -> dynamic array conversion is seriously a nasty misfeature that ought to be killed with fire. It leads to bugs like this: struct Database { int[] data; void set(int[] _data) { data = _data; } } void myFunc(ref Database db) { int[3] x; db.set(x); // oops } ) T -- Once the bikeshed is up for painting, the rainbow won't suffice. -- Andrei Alexandrescu
Jun 30 2020
parent reply tsbockman <thomas.bockman gmail.com> writes:
On Tuesday, 30 June 2020 at 16:36:45 UTC, H. S. Teoh wrote:
 And on that note, this implicit static -> dynamic array 
 conversion is seriously a nasty misfeature that ought to be 
 killed with fire. It leads to bugs like this:

 	struct Database {
 		int[] data;
 		void set(int[] _data) {
 			data = _data;
 		}
 	}
 	void myFunc(ref Database db) {
 		int[3] x;
 		db.set(x);	// oops
 	}
If you want the compiler to stop you from accidentally keeping references to stack variables past the end of their scope, you need to annotate your functions safe and compile with -preview=dip1000: https://run.dlang.io/is/3VdDaN Furthermore, the problem your example shows has nothing to do with implicit static to dynamic array conversion, as without safe the same error can easily be committed with non-array types: https://run.dlang.io/is/nBjibd
Jul 01 2020
parent tsbockman <thomas.bockman gmail.com> writes:
On Wednesday, 1 July 2020 at 20:05:51 UTC, tsbockman wrote:
 If you want the compiler to stop you from accidentally keeping 
 references to stack variables past the end of their scope, you 
 need to annotate your functions  safe and compile with 
 -preview=dip1000: https://run.dlang.io/is/3VdDaN

 Furthermore, the problem your example shows has nothing to do 
 with implicit static to dynamic array conversion, as without 
  safe the same error can easily be committed with non-array 
 types: https://run.dlang.io/is/nBjibd
Hmm. Those run.dlang.io short links seem to allow editing of the code, so I'd better paste it here for permanence: // Compile with -preview=dip1000 struct Database { int[] data; void set(int[] _data) safe { data = _data; } } void myFunc(ref Database db) safe { int[3] x; db.set(x); // This is a compile-time error, as it should be. } Database theDB; void main() { myFunc(theDB); } // This version shows that the problem is not using safe and dip1000, // not anything to do with arrays: struct Database { int* data; void set(ref int _data) { data = &_data; } } void myFunc(ref Database db) { int x; db.set(x); // oops } Database theDB; void main() { myFunc(theDB); }
Jul 01 2020
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/30/20 12:22 PM, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:
 
 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5
 
 Why does such code compile? I don't think this should be permitted, 
 because it's easy to make a mistake (when you wanted foo[index] but 
 forgot the []). If someone wants to assign a value to every element they 
 could do foo[] = 5; instead which is explicit.
That's a feature. I don't think it's going away. The problem of accidental assignment is probably not very common. -Steve
Jun 30 2020
next sibling parent reply JN <666total wp.pl> writes:
On Tuesday, 30 June 2020 at 16:37:12 UTC, Steven Schveighoffer 
wrote:
 That's a feature. I don't think it's going away. The problem of 
 accidental assignment is probably not very common.

 -Steve
What is the benefit of this feature? I feel like D has quite a few of such "features". I like my code to be explicit, even at a cost of some extra typing, rather than get bitten by some unexpected implicit behavior.
Jun 30 2020
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote:
 I like my code to be explicit, even at a cost of some extra 
 typing, rather than get bitten by some unexpected implicit 
 behavior.
I agree, I think ALL implicit slicing of static arrays are problematic and should be removed. If you want to set it all or slice it for any other reason, just put on the [].
Jun 30 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jun 30, 2020 at 04:50:07PM +0000, Adam D. Ruppe via Digitalmars-d-learn
wrote:
 On Tuesday, 30 June 2020 at 16:41:50 UTC, JN wrote:
 I like my code to be explicit, even at a cost of some extra typing,
 rather than get bitten by some unexpected implicit behavior.
I agree, I think ALL implicit slicing of static arrays are problematic and should be removed. If you want to set it all or slice it for any other reason, just put on the [].
We've known this for at least 4 years, yet nothing has been done about it. :-( https://issues.dlang.org/show_bug.cgi?id=15932 The problem isn't just safety, which is partly addressed by dip1000, but also mistakes of the kind the OP posted. Basically, it's a misfeature with many ill side-effects all in the questionable name of convenience. It's time we got rid of it. T -- Truth, Sir, is a cow which will give [skeptics] no more milk, and so they are gone to milk the bull. -- Sam. Johnson
Jun 30 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/30/20 12:37 PM, Steven Schveighoffer wrote:
 On 6/30/20 12:22 PM, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:

 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5

 Why does such code compile? I don't think this should be permitted, 
 because it's easy to make a mistake (when you wanted foo[index] but 
 forgot the []). If someone wants to assign a value to every element 
 they could do foo[] = 5; instead which is explicit.
That's a feature. I don't think it's going away. The problem of accidental assignment is probably not very common.
I take it back, I didn't realize this wasn't something that happened with dynamic arrays: int[] dyn = [1, 2, 3]; dyn = 5; // error dyn[] = 5; // ok, brackets required I would say that's a decent precedent to deprecate and remove that functionality. -Steve
Jun 30 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 6/30/20 12:37 PM, Steven Schveighoffer wrote:
[...]
 I take it back, I didn't realize this wasn't something that happened
 with dynamic arrays:
 
 int[] dyn = [1, 2, 3];
 
 dyn = 5; // error
 dyn[] = 5; // ok, brackets required
 
 I would say that's a decent precedent to deprecate and remove that
 functionality.
[...] Could you add this info to the bugzilla issue as additional evidence that this (mis)feature should be removed? https://issues.dlang.org/show_bug.cgi?id=15932 T -- "640K ought to be enough" -- Bill G. (allegedly), 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.
Jun 30 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/30/20 2:22 PM, H. S. Teoh wrote:
 On Tue, Jun 30, 2020 at 02:06:13PM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 6/30/20 12:37 PM, Steven Schveighoffer wrote:
[...]
 I take it back, I didn't realize this wasn't something that happened
 with dynamic arrays:

 int[] dyn = [1, 2, 3];

 dyn = 5; // error
 dyn[] = 5; // ok, brackets required

 I would say that's a decent precedent to deprecate and remove that
 functionality.
[...] Could you add this info to the bugzilla issue as additional evidence that this (mis)feature should be removed? https://issues.dlang.org/show_bug.cgi?id=15932
That's a different issue. In the case of: staticarr = 5; There is no issue with lifetime management or memory safety. It's possible that fixing 15932 would fix this issue too, but it's possible that's not true (we are assuming it's the implicit cast that is causing this issue, but it might be separately implemented). -Steve
Jun 30 2020
prev sibling next sibling parent tastyminerals <tastyminerals gmail.com> writes:
On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:

 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5

 Why does such code compile? I don't think this should be 
 permitted, because it's easy to make a mistake (when you wanted 
 foo[index] but forgot the []). If someone wants to assign a 
 value to every element they could do foo[] = 5; instead which 
 is explicit.
auch, that is very nasty. Thanks for posting. This is a good example for D gotchas.
Jun 30 2020
prev sibling next sibling parent psycha0s <box mail.com> writes:
On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
 Why does such code compile? I don't think this should be 
 permitted, because it's easy to make a mistake (when you wanted 
 foo[index] but forgot the []). If someone wants to assign a 
 value to every element they could do foo[] = 5; instead which 
 is explicit.
Totally agree. In most of cases implicit actions lead to errors. Even if they have a specific use case and really convenient.
Jul 01 2020
prev sibling parent reply Nathan S. <no.public.email example.com> writes:
On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:

 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5

 Why does such code compile? I don't think this should be 
 permitted, because it's easy to make a mistake (when you wanted 
 foo[index] but forgot the []). If someone wants to assign a 
 value to every element they could do foo[] = 5; instead which 
 is explicit.
What's your opinion on using that syntax in the initial declaration, like `float[16] foo = 0`?
Jul 01 2020
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/1/20 11:57 AM, Nathan S. wrote:
 On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:

 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5

 Why does such code compile? I don't think this should be permitted, 
 because it's easy to make a mistake (when you wanted foo[index] but 
 forgot the []). If someone wants to assign a value to every element 
 they could do foo[] = 5; instead which is explicit.
What's your opinion on using that syntax in the initial declaration, like `float[16] foo = 0`?
It's important to keep at least something that allows such setting. It would be reasonable to do this with a function as well. Is it possible to have the initialization syntax work differently from the assignment (i.e. allow the initialization as above, but require the brackets for assignment)? -Steve
Jul 01 2020
prev sibling parent JN <666total wp.pl> writes:
On Wednesday, 1 July 2020 at 15:57:24 UTC, Nathan S. wrote:
 On Tuesday, 30 June 2020 at 16:22:57 UTC, JN wrote:
 Spent some time debugging because I didn't notice it at first, 
 essentially something like this:

 int[3] foo = [1, 2, 3];
 foo = 5;
 writeln(foo);   // 5, 5, 5

 Why does such code compile? I don't think this should be 
 permitted, because it's easy to make a mistake (when you 
 wanted foo[index] but forgot the []). If someone wants to 
 assign a value to every element they could do foo[] = 5; 
 instead which is explicit.
What's your opinion on using that syntax in the initial declaration, like `float[16] foo = 0`?
I don't like it. I'd prefer: float[16] foo = [ 0 ]; or float[16] foo = { 0 }; or float[16] foo(0);
Jul 01 2020