www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - array setting : Whats going in here?

reply claptrap <clap trap.com> writes:
char[] foo;
foo.length = 4;
foo[] = 'a'; // ok sets all elements
foo[] = "a"; // range error at runtime?
foo[] = "ab"; // range error at runtime?

So I meant to init with a char literal but accidently used double 
quotes. Should that even compile? Shouldn't the compiler at least 
complain when trying to init with "ab"?
Oct 06 2023
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Sat, Oct 07, 2023 at 12:00:48AM +0000, claptrap via Digitalmars-d-learn
wrote:
 
 char[] foo;
 foo.length = 4;
 foo[] = 'a'; // ok sets all elements
 foo[] = "a"; // range error at runtime?
 foo[] = "ab"; // range error at runtime?
 
 So I meant to init with a char literal but accidently used double
 quotes.  Should that even compile? Shouldn't the compiler at least
 complain when trying to init with "ab"?
If you want initialization, don't slice the target array. For example: char[] foo = "a"; Or: char[] foo; ... foo = "a"; When you write `foo[]` you're taking a slice of the array, and in that case if the lengths of both sides of the assignment don't match, you'll get a runtime error. T -- Always remember that you are unique. Just like everybody else. -- despair.com
Oct 06 2023
parent reply claptrap <clap trap.com> writes:
On Saturday, 7 October 2023 at 00:49:39 UTC, H. S. Teoh wrote:
 On Sat, Oct 07, 2023 at 12:00:48AM +0000, claptrap via 
 Digitalmars-d-learn wrote:

 When you write `foo[]` you're taking a slice of the array, and 
 in that case if the lengths of both sides of the assignment 
 don't match, you'll get a runtime error.
How did I not know that?? I'd always thought "foo[] = x" was just special syntax for setting all the elements to the same value. Thanks.
Oct 07 2023
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, October 7, 2023 10:59:47 AM MDT claptrap via Digitalmars-d-learn 
wrote:
 On Saturday, 7 October 2023 at 00:49:39 UTC, H. S. Teoh wrote:
 On Sat, Oct 07, 2023 at 12:00:48AM +0000, claptrap via
 Digitalmars-d-learn wrote:


 When you write `foo[]` you're taking a slice of the array, and
 in that case if the lengths of both sides of the assignment
 don't match, you'll get a runtime error.
How did I not know that?? I'd always thought "foo[] = x" was just special syntax for setting all the elements to the same value. Thanks.
It is, but it's assigning them to the elements in the slice, and if you slice the entire array, then you're assigning to every element in the array. e.g. auto foo = new int[](6); foo[] = 5; assert(foo == [5, 5, 5, 5, 5, 5]); Alternatively, you can assign to a slice that refers to just some of the elements of the array being sliced. e.g. auto foo = new int[](6); foo[0 .. 3] = 5; assert(foo == [5, 5, 5, 0, 0, 0]); And if you're assigning another array to it rather than a value of the element type, then it assigns the individual elements. e.g. auto foo = new int[](6); auto bar = [1, 2, 3, 4]; foo[0 .. 4] = bar[]; assert(foo == [1, 2, 3, 4, 0, 0]); And when you assign an array/slice like that, the number of elements on each side must match. So, if you do any of foo[] = bar[]; or foo[] = bar; then foo and bar must have the same length (and must have compatible element types). The difference between those and foo = bar; is that assigning to foo[] results in the elements being copied, whereas assigning directly to foo results in foo being a slice of bar. auto foo = new int[](6); auto bar = new int[](6); foo[] = bar[]; assert(foo == bar); assert(foo !is bar); foo = bar[]; assert(foo is bar); So, it's probably best to think of foo[] = x; as being a way to assign to each individual element in that slice of foo rather than assigning to foo. And then which elements are assigned to depends on how much of foo you slice, and how those elements are assigned to depends on the type of x. - Jonathan M Davis
Oct 07 2023
prev sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Saturday, 7 October 2023 at 00:00:48 UTC, claptrap wrote:
 char[] foo;
 foo.length = 4;
 foo[] = 'a'; // ok sets all elements
 foo[] = "a"; // range error at runtime?
 foo[] = "ab"; // range error at runtime?

 So I meant to init with a char literal but accidently used 
 double quotes. Should that even compile? Shouldn't the compiler 
 at least complain when trying to init with "ab"?
Even though you now have gotten answers, I still agree with you that there should be some kind of "warning" or suggestion like, did you mean to assign incompatible types? It could just check the element type and see if it matches the rhs type.
Oct 08 2023
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, October 8, 2023 8:08:46 AM MDT Imperatorn via Digitalmars-d-learn 
wrote:
 On Saturday, 7 October 2023 at 00:00:48 UTC, claptrap wrote:
 char[] foo;
 foo.length = 4;
 foo[] = 'a'; // ok sets all elements
 foo[] = "a"; // range error at runtime?
 foo[] = "ab"; // range error at runtime?

 So I meant to init with a char literal but accidently used
 double quotes. Should that even compile? Shouldn't the compiler
 at least complain when trying to init with "ab"?
Even though you now have gotten answers, I still agree with you that there should be some kind of "warning" or suggestion like, did you mean to assign incompatible types? It could just check the element type and see if it matches the rhs type.
Except that in those examples, they _do_ match. It's perfectly valid to copy elements of a string to a char[]. It's just copying immutable(char) to char. The compiler would complain if it couldn't implicitly convert the element type in the array being assigned from to the element type in the array being assigned to. The problem here is simply that the lengths of the arrays don't match. And in general, the compiler has no way of knowing whether the lengths match, because the lengths are dynamic. In this particular case, it could figure it out if it did sufficient flow analysis, but that's the sort of thing that typically isn't done in D, because it gets to be expensive and tends to result in inconsistent behavior, because small changes to the code could drastically change what the compiler is able to figure out. If the lengths were static, then the compiler actually would complain. e.g. foo[0 .. 3] = bar[1 .. 2]; would result in a compilation error such as q.d(5): Error: mismatched array lengths 3 and 1 for assignment `foo[0..3] = bar[1..2]` So, the compiler will complain both if it can't implicitly convert the element types to make the assignment work and if it can statically see that the lengths of the arrays don't much. As such, I'm not sure that there's actually anything that the compiler could do here to catch the problem in the OP's case (at least not without doing code flow analysis, which isn't going to happen). - Jonathan M Davis
Oct 08 2023
parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Monday, 9 October 2023 at 02:19:20 UTC, Jonathan M Davis wrote:
 On Sunday, October 8, 2023 8:08:46 AM MDT Imperatorn via 
 Digitalmars-d-learn wrote:
 [...]
Except that in those examples, they _do_ match. It's perfectly valid to copy elements of a string to a char[]. It's just copying immutable(char) to char. The compiler would complain if it couldn't implicitly convert the element type in the array being assigned from to the element type in the array being assigned to. The problem here is simply that the lengths of the arrays don't match. [...]
Thanks, I think I read the code a little too fast
Oct 09 2023