Jump to page: 1 2 3
Thread overview
Re: array of elements of various sybtypes
Jan 26, 2011
spir
Jan 26, 2011
spir
Jan 26, 2011
bearophile
Jan 27, 2011
spir
Jan 27, 2011
bearophile
Jan 26, 2011
Jonathan M Davis
Jan 26, 2011
spir
Jan 26, 2011
Jonathan M Davis
Jan 27, 2011
Jonathan M Davis
Jan 27, 2011
Andrej Mitrovic
Jan 27, 2011
spir
Jan 28, 2011
spir
Jan 27, 2011
spir
Jan 27, 2011
Andrej Mitrovic
Jan 27, 2011
spir
Jan 28, 2011
spir
January 26, 2011
On 01/26/2011 06:27 PM, spir wrote:
> Hello,
>
> This fails:
>
> class T0 {}
> class T1 : T0 {}
> class T2 : T0 {}
>
> unittest {
> auto t1 = new T1();
> auto t2 = new T2();
> T0[] ts = [t1, t2];
> }
>
> Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
> __trials__.T2
> Error: cannot implicitly convert expression ([(__error),t2]) of type T2[] to T0[]
>
> I guess it should be accepted due to explicite typing 'T0[]'. What do you
> think? D first determines the type of the last element (always the last one),
> here T2. Then, /ignoring/ the array's defined type, tries to cast other
> elements to the same type T2. It should instead, I guess, check all elements
> are compatible with the defined array type.
> An additional enigma is why the failing element t1 is said to be of supertype
> T0 --which is also correct-- while it retained t2's exact type T2. ???
>
> Anyway, is there a workaround?

PS: this works, but I would prefere a solution with all casting:
    T0[] ts = [cast(T0)t1, cast(T0)t2];
I consider this issue a bug, at least when the array is explicitely typed. What do you think?

Denis
-- 
_________________
vita es estrany
spir.wikidot.com

January 26, 2011
On Wed, 26 Jan 2011 12:30:17 -0500, spir <denis.spir@gmail.com> wrote:

> On 01/26/2011 06:27 PM, spir wrote:
>> Hello,
>>
>> This fails:
>>
>> class T0 {}
>> class T1 : T0 {}
>> class T2 : T0 {}
>>
>> unittest {
>> auto t1 = new T1();
>> auto t2 = new T2();
>> T0[] ts = [t1, t2];
>> }
>>
>> Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
>> __trials__.T2
>> Error: cannot implicitly convert expression ([(__error),t2]) of type T2[] to T0[]
>>
>> I guess it should be accepted due to explicite typing 'T0[]'. What do you
>> think? D first determines the type of the last element (always the last one),
>> here T2. Then, /ignoring/ the array's defined type, tries to cast other
>> elements to the same type T2. It should instead, I guess, check all elements
>> are compatible with the defined array type.
>> An additional enigma is why the failing element t1 is said to be of supertype
>> T0 --which is also correct-- while it retained t2's exact type T2. ???
>>
>> Anyway, is there a workaround?
>
> PS: this works, but I would prefere a solution with all casting:
>      T0[] ts = [cast(T0)t1, cast(T0)t2];
> I consider this issue a bug, at least when the array is explicitely typed. What do you think?

It's not a bug, the type of an expression does not depend on the type it's assigned to.  Essentially [t1, t2] is evaluated *before* looking at what it's assigned to.

And the array literal code now uses the most 'compatible' type to determine the type of the array (used to be hard-typed to type of first element).  Obviously it doesn't work correctly here, but I'm not sure it could really work correctly.  I think maybe if one of those elements had type T0, it might actually compile.

-Steve
January 26, 2011
On Wednesday, January 26, 2011 09:30:17 spir wrote:
> On 01/26/2011 06:27 PM, spir wrote:
> > Hello,
> > 
> > This fails:
> > 
> > class T0 {}
> > class T1 : T0 {}
> > class T2 : T0 {}
> > 
> > unittest {
> > auto t1 = new T1();
> > auto t2 = new T2();
> > T0[] ts = [t1, t2];
> > }
> > 
> > Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
> > __trials__.T2
> > Error: cannot implicitly convert expression ([(__error),t2]) of type T2[]
> > to T0[]
> > 
> > I guess it should be accepted due to explicite typing 'T0[]'. What do you
> > think? D first determines the type of the last element (always the last
> > one), here T2. Then, /ignoring/ the array's defined type, tries to cast
> > other elements to the same type T2. It should instead, I guess, check
> > all elements are compatible with the defined array type.
> > An additional enigma is why the failing element t1 is said to be of
> > supertype T0 --which is also correct-- while it retained t2's exact type
> > T2. ???
> > 
> > Anyway, is there a workaround?
> 
> PS: this works, but I would prefere a solution with all casting:
>      T0[] ts = [cast(T0)t1, cast(T0)t2];
> I consider this issue a bug, at least when the array is explicitely typed.
> What do you think?

The problem is that the expression to the right of the assignment is completely independent from the assignment. The expression results in whatever type it results in, and _then_ it's assigned to the variable. In this case, its a variable declaration as opposed to an assignment, so it's initializing the variable instead of assigning to it, but from the perspective of the expression, there's no difference. It's just like how you can't overload functions on return type. How the result of the function is used is irrelevant to evaluating the function. In this case, how the result of the expression is used is irrelevant to evaluating it. It would actually probably be a pretty big language change to try and make it otherwise, and I'm not sure what all the ramifications are. I can see why you'd want it, but I really don't expect it to happen. Walter just wouldn't go for it. So, it's not a bug at all.

- Jonathan M Davis
January 26, 2011
On 01/26/2011 07:32 PM, Jonathan M Davis wrote:
> On Wednesday, January 26, 2011 09:30:17 spir wrote:
>> On 01/26/2011 06:27 PM, spir wrote:
>>> Hello,
>>>
>>> This fails:
>>>
>>> class T0 {}
>>> class T1 : T0 {}
>>> class T2 : T0 {}
>>>
>>> unittest {
>>> auto t1 = new T1();
>>> auto t2 = new T2();
>>> T0[] ts = [t1, t2];
>>> }
>>>
>>> Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
>>> __trials__.T2
>>> Error: cannot implicitly convert expression ([(__error),t2]) of type T2[]
>>> to T0[]
>>>
>>> I guess it should be accepted due to explicite typing 'T0[]'. What do you
>>> think? D first determines the type of the last element (always the last
>>> one), here T2. Then, /ignoring/ the array's defined type, tries to cast
>>> other elements to the same type T2. It should instead, I guess, check
>>> all elements are compatible with the defined array type.
>>> An additional enigma is why the failing element t1 is said to be of
>>> supertype T0 --which is also correct-- while it retained t2's exact type
>>> T2. ???
>>>
>>> Anyway, is there a workaround?
>>
>> PS: this works, but I would prefere a solution with all casting:
>>       T0[] ts = [cast(T0)t1, cast(T0)t2];
>> I consider this issue a bug, at least when the array is explicitely typed.
>> What do you think?
>
> The problem is that the expression to the right of the assignment is completely
> independent from the assignment. The expression results in whatever type it
> results in, and _then_ it's assigned to the variable. In this case, its a
> variable declaration as opposed to an assignment, so it's initializing the
> variable instead of assigning to it, but from the perspective of the expression,
> there's no difference. It's just like how you can't overload functions on return
> type.

Yop, had this problem a could of times as well.

>How the result of the function is used is irrelevant to evaluating the
> function. In this case, how the result of the expression is used is irrelevant
> to evaluating it. It would actually probably be a pretty big language change to
> try and make it otherwise, and I'm not sure what all the ramifications are. I can
> see why you'd want it, but I really don't expect it to happen. Walter just
> wouldn't go for it. So, it's not a bug at all.

Right, I understand the point of evaluating the expression independantly of its use in a second phase.
But then, how are we supposed to have such arrays? Note that:
	T0[] ts;
	ts = [t1, t2];
fails exactly the same way (and for the same reason). How can I feed ts?

Denis
-- 
_________________
vita es estrany
spir.wikidot.com

January 26, 2011
On Wednesday, January 26, 2011 15:07:09 spir wrote:
> On 01/26/2011 07:32 PM, Jonathan M Davis wrote:
> > On Wednesday, January 26, 2011 09:30:17 spir wrote:
> >> On 01/26/2011 06:27 PM, spir wrote:
> >>> Hello,
> >>> 
> >>> This fails:
> >>> 
> >>> class T0 {}
> >>> class T1 : T0 {}
> >>> class T2 : T0 {}
> >>> 
> >>> unittest {
> >>> auto t1 = new T1();
> >>> auto t2 = new T2();
> >>> T0[] ts = [t1, t2];
> >>> }
> >>> 
> >>> Error: cannot implicitly convert expression (t1) of type __trials__.T0
> >>> to __trials__.T2
> >>> Error: cannot implicitly convert expression ([(__error),t2]) of type
> >>> T2[] to T0[]
> >>> 
> >>> I guess it should be accepted due to explicite typing 'T0[]'. What do you think? D first determines the type of the last element (always the last one), here T2. Then, /ignoring/ the array's defined type, tries to cast other elements to the same type T2. It should instead, I guess, check all elements are compatible with the defined array type. An additional enigma is why the failing element t1 is said to be of supertype T0 --which is also correct-- while it retained t2's exact type T2. ???
> >>> 
> >>> Anyway, is there a workaround?
> >> 
> >> PS: this works, but I would prefere a solution with all casting:
> >>       T0[] ts = [cast(T0)t1, cast(T0)t2];
> >> 
> >> I consider this issue a bug, at least when the array is explicitely typed. What do you think?
> > 
> > The problem is that the expression to the right of the assignment is completely independent from the assignment. The expression results in whatever type it results in, and _then_ it's assigned to the variable. In this case, its a variable declaration as opposed to an assignment, so it's initializing the variable instead of assigning to it, but from the perspective of the expression, there's no difference. It's just like how you can't overload functions on return type.
> 
> Yop, had this problem a could of times as well.
> 
> >How the result of the function is used is irrelevant to evaluating the
> >
> > function. In this case, how the result of the expression is used is irrelevant to evaluating it. It would actually probably be a pretty big language change to try and make it otherwise, and I'm not sure what all the ramifications are. I can see why you'd want it, but I really don't expect it to happen. Walter just wouldn't go for it. So, it's not a bug at all.
> 
> Right, I understand the point of evaluating the expression independantly of
> its use in a second phase.
> But then, how are we supposed to have such arrays? Note that:
> 	T0[] ts;
> 	ts = [t1, t2];
> fails exactly the same way (and for the same reason). How can I feed ts?

I believe that it's supposed to take the common type of t1 and t2 and make the result an array of that type. So, assuming that the common type is T0, then it should work. However, it's not currently implemented that way. You could always create a bug report so that it doesn't get lost (assuming that no such report already exists).

- Jonathan M Davis
January 26, 2011
On 01/26/2011 07:26 PM, Steven Schveighoffer wrote:
> On Wed, 26 Jan 2011 12:30:17 -0500, spir <denis.spir@gmail.com> wrote:
>
>> On 01/26/2011 06:27 PM, spir wrote:
>>> Hello,
>>>
>>> This fails:
>>>
>>> class T0 {}
>>> class T1 : T0 {}
>>> class T2 : T0 {}
>>>
>>> unittest {
>>> auto t1 = new T1();
>>> auto t2 = new T2();
>>> T0[] ts = [t1, t2];
>>> }
>>>
>>> Error: cannot implicitly convert expression (t1) of type __trials__.T0 to
>>> __trials__.T2
>>> Error: cannot implicitly convert expression ([(__error),t2]) of type T2[] to
>>> T0[]
>>>
>>> I guess it should be accepted due to explicite typing 'T0[]'. What do you
>>> think? D first determines the type of the last element (always the last one),
>>> here T2. Then, /ignoring/ the array's defined type, tries to cast other
>>> elements to the same type T2. It should instead, I guess, check all elements
>>> are compatible with the defined array type.
>>> An additional enigma is why the failing element t1 is said to be of supertype
>>> T0 --which is also correct-- while it retained t2's exact type T2. ???
>>>
>>> Anyway, is there a workaround?
>>
>> PS: this works, but I would prefere a solution with all casting:
>> T0[] ts = [cast(T0)t1, cast(T0)t2];
>> I consider this issue a bug, at least when the array is explicitely typed.
>> What do you think?
>
> It's not a bug, the type of an expression does not depend on the type it's
> assigned to. Essentially [t1, t2] is evaluated *before* looking at what it's
> assigned to.
>
> And the array literal code now uses the most 'compatible' type to determine the
> type of the array (used to be hard-typed to type of first element). Obviously
> it doesn't work correctly here, but I'm not sure it could really work
> correctly. I think maybe if one of those elements had type T0, it might
> actually compile.

The said element should be, I guess, the last one (seems D start evaluating elements from the right?).
EDIT: this works:
    auto t0 = new T0();
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] ts = [t0, t1, t2];
Seems D check compatibility between actual element types. In the original case of [t1, t2], it does not "see" that T1 & T2 have a common supertype.
I would like to know why the original error message assigns speaks of type T0 (for t1, obviously).

What about a workaround? Hum... This works:

void feed (T) (ref T[] array, T[] elements...) {
    foreach (element ; elements)
        array ~= element;
}
unittest {
    auto t1 = new T1();
    auto t2 = new T2();
    T0[] array;
    array.feed(t1, t2);
    writeln(array);
}

The trick indeed is using '...'. May feed be useful in std.array? (With a variant for AAs?)
(Called it feed instead of init because it can also extend a non-empty array, with a set of new elements one could not write literally, neither.)

Denis
-- 
_________________
vita es estrany
spir.wikidot.com

January 26, 2011
spir:

> May feed be useful in std.array?

Better to fix array litertals instead.

Bye,
bearophile
January 27, 2011
On 01/27/2011 12:37 AM, bearophile wrote:
> spir:
>
>> May feed be useful in std.array?
>
> Better to fix array litertals instead.

Maybe, but (in this case) array literals are OK. We need a way to feed arrays according to a common supertype that may be the actual exact type of no provided element.
Now, I agree that array literals (and output formats) have /other/ issues. But how would fixing them halp in this case?

Denis
-- 
_________________
vita es estrany
spir.wikidot.com

January 27, 2011
On Wed, 26 Jan 2011 18:28:12 -0500, Jonathan M Davis <jmdavisProg@gmx.com> wrote:


> I believe that it's supposed to take the common type of t1 and t2 and make the
> result an array of that type. So, assuming that the common type is T0, then it
> should work. However, it's not currently implemented that way. You could always
> create a bug report so that it doesn't get lost (assuming that no such report
> already exists).
>

Object could also be the common type.  When there exists multiple possibilities, and none of the possibilities are types being passed to the array literal, I think it just gives up (D usually gives up in the face of ambiguity, instead of possibly making the wrong decision).

But the problem here appears that there is no way to *force* it to make the right decision.

I'd like to see cast(T0[])[...] work, I think that should solve the problem.

-Steve
January 27, 2011
On Wednesday 26 January 2011 18:59:50 Steven Schveighoffer wrote:
> On Wed, 26 Jan 2011 18:28:12 -0500, Jonathan M Davis <jmdavisProg@gmx.com>
> 
> wrote:
> > I believe that it's supposed to take the common type of t1 and t2 and
> > make the
> > result an array of that type. So, assuming that the common type is T0,
> > then it
> > should work. However, it's not currently implemented that way. You could
> > always
> > create a bug report so that it doesn't get lost (assuming that no such
> > report
> > already exists).
> 
> Object could also be the common type.  When there exists multiple possibilities, and none of the possibilities are types being passed to the array literal, I think it just gives up (D usually gives up in the face of ambiguity, instead of possibly making the wrong decision).
> 
> But the problem here appears that there is no way to *force* it to make the right decision.
> 
> I'd like to see cast(T0[])[...] work, I think that should solve the
> problem.

It probably doesn't for the exact same reason that the assignment didn't do it. The expression is evaluated and _then_ it's cast. So, if the expression isn't valid in and of itself, it fails.

- Jonathan M Davis
« First   ‹ Prev
1 2 3