Thread overview
array setting : Whats going in here?
Oct 07, 2023
claptrap
Oct 07, 2023
H. S. Teoh
Oct 07, 2023
claptrap
Oct 07, 2023
Jonathan M Davis
Oct 08, 2023
Imperatorn
Oct 09, 2023
Jonathan M Davis
Oct 09, 2023
Imperatorn
October 07, 2023

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"?

October 06, 2023
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
October 07, 2023
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.
October 07, 2023
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



October 08, 2023

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.

October 08, 2023
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



October 09, 2023
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