Jump to page: 1 27  
Page
Thread overview
Type inference and overloaded functions
Dec 10, 2013
FreeSlave
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Ali Çehreli
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Kenji Hara
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Namespace
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Namespace
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Namespace
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Namespace
Dec 10, 2013
bearophile
Dec 10, 2013
Namespace
Dec 10, 2013
bearophile
Dec 10, 2013
Namespace
Dec 10, 2013
Namespace
Dec 11, 2013
Namespace
Dec 11, 2013
Namespace
Dec 11, 2013
Ali Çehreli
Dec 11, 2013
Namespace
Dec 11, 2013
Chris Cain
Dec 11, 2013
Namespace
Dec 11, 2013
Namespace
Dec 11, 2013
bearophile
Dec 11, 2013
Namespace
Dec 11, 2013
bearophile
Dec 11, 2013
Namespace
Dec 11, 2013
bearophile
Dec 12, 2013
Namespace
Dec 12, 2013
bearophile
Dec 12, 2013
Timothee Cour
Dec 12, 2013
bearophile
Dec 12, 2013
bearophile
Dec 13, 2013
Namespace
Dec 13, 2013
bearophile
Dec 13, 2013
Namespace
Dec 17, 2013
bearophile
Dec 18, 2013
Namespace
Dec 18, 2013
bearophile
Dec 19, 2013
Ali Çehreli
Dec 13, 2013
Kenji Hara
Dec 13, 2013
Maxim Fomin
Dec 13, 2013
Jonathan M Davis
Dec 12, 2013
Namespace
Dec 12, 2013
bearophile
Dec 12, 2013
bearophile
Dec 12, 2013
bearophile
Dec 12, 2013
bearophile
Dec 12, 2013
Ali Çehreli
Dec 12, 2013
bearophile
Dec 12, 2013
Namespace
Dec 10, 2013
Kenji Hara
Dec 10, 2013
Jonathan M Davis
Dec 10, 2013
Marco Leise
Dec 10, 2013
Marco Leise
Dec 10, 2013
Timon Gehr
Dec 10, 2013
Dicebot
Dec 10, 2013
Marco Leise
Dec 10, 2013
Kenji Hara
Dec 10, 2013
Marco Leise
December 10, 2013
I just found weird D behavior about inference of array types.

Let's suppose we have these overloaded functions:

import std.stdio;

void bar(const(int[3]) arr)
{
    writeln("static array");
}

void bar(const(int[]) arr)
{
    writeln("array slice");
}

// In main we have something like that:
int main(string[] args)
{
    bar([1,2,3]);
    writeln(typeof([1,2,3]).stringof);
    return 0;
}

Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3].
December 10, 2013
On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
> I just found weird D behavior about inference of array types.
> 
> Let's suppose we have these overloaded functions:
> 
> import std.stdio;
> 
> void bar(const(int[3]) arr)
> {
>      writeln("static array");
> }
> 
> void bar(const(int[]) arr)
> {
>      writeln("array slice");
> }
> 
> // In main we have something like that:
> int main(string[] args)
> {
>      bar([1,2,3]);
>      writeln(typeof([1,2,3]).stringof);
>      return 0;
> }
> 
> Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3].

Array literals are always dynamic arrays. int[3] is a static array.

- Jonathan M Davis
December 10, 2013
On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
> On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
>> I just found weird D behavior about inference of array types.
>>
>> Let's suppose we have these overloaded functions:
>>
>> import std.stdio;
>>
>> void bar(const(int[3]) arr)
>> {
>>       writeln("static array");
>> }
>>
>> void bar(const(int[]) arr)
>> {
>>       writeln("array slice");
>> }
>>
>> // In main we have something like that:
>> int main(string[] args)
>> {
>>       bar([1,2,3]);
>>       writeln(typeof([1,2,3]).stringof);
>>       return 0;
>> }
>>
>> Weird thing is that the static array version of bar is called,
>> but typeof().stringof is int[], not int[3].
>
> Array literals are always dynamic arrays. int[3] is a static array.
>
> - Jonathan M Davis
>

The original question is valid then: [1,2,3] goes to the static array overload.

Ali

December 10, 2013
On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:
> On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
> > On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
> >> I just found weird D behavior about inference of array types.
> >> 
> >> Let's suppose we have these overloaded functions:
> >> 
> >> import std.stdio;
> >> 
> >> void bar(const(int[3]) arr)
> >> {
> >> 
> >>       writeln("static array");
> >> 
> >> }
> >> 
> >> void bar(const(int[]) arr)
> >> {
> >> 
> >>       writeln("array slice");
> >> 
> >> }
> >> 
> >> // In main we have something like that:
> >> int main(string[] args)
> >> {
> >> 
> >>       bar([1,2,3]);
> >>       writeln(typeof([1,2,3]).stringof);
> >>       return 0;
> >> 
> >> }
> >> 
> >> Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3].
> > 
> > Array literals are always dynamic arrays. int[3] is a static array.
> > 
> > - Jonathan M Davis
> 
> The original question is valid then: [1,2,3] goes to the static array overload.

Then AFAIK, that's a bug. The type of array literals is always a dynamic array, so they should match dynamic array overloads rather than static array overloads, or if they match both due to an implicit conversion, there should be an ambiguity error. Choosing the static array overload over the dynamic one is just plain wrong.

- Jonathan M Davis

December 10, 2013
On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis wrote:
> On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:
>> On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
>> > On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
>> >> I just found weird D behavior about inference of array types.
>> >> 
>> >> Let's suppose we have these overloaded functions:
>> >> 
>> >> import std.stdio;
>> >> 
>> >> void bar(const(int[3]) arr)
>> >> {
>> >> 
>> >>       writeln("static array");
>> >> 
>> >> }
>> >> 
>> >> void bar(const(int[]) arr)
>> >> {
>> >> 
>> >>       writeln("array slice");
>> >> 
>> >> }
>> >> 
>> >> // In main we have something like that:
>> >> int main(string[] args)
>> >> {
>> >> 
>> >>       bar([1,2,3]);
>> >>       writeln(typeof([1,2,3]).stringof);
>> >>       return 0;
>> >> 
>> >> }
>> >> 
>> >> Weird thing is that the static array version of bar is called,
>> >> but typeof().stringof is int[], not int[3].
>> > 
>> > Array literals are always dynamic arrays. int[3] is a static array.
>> > 
>> > - Jonathan M Davis
>> 
>> The original question is valid then: [1,2,3] goes to the static array
>> overload.
>
> Then AFAIK, that's a bug. The type of array literals is always a dynamic
> array, so they should match dynamic array overloads rather than static array
> overloads, or if they match both due to an implicit conversion, there should
> be an ambiguity error. Choosing the static array overload over the dynamic one
> is just plain wrong.

This is an intended behavior. An array literal has dynamic array type *by default*.
But all of literals in D behave as polymorphic.

char c = 'A';   // character literal has char type by default
dchar d = 'A';  // but it may be implicitly typed as wchar/dchar

string str = "hello";
dstring dstr = "hello";  // string literal is implicitly typed as dstring

int[] darr = [1,2,3];
int[3] darr = [1,2,3];   // implicitly typed as int[3]

So, an array literal [1,2,3] is implicitly convertible both to int[] and int[3].
And, int[3] is more specialized than int[], so overload resolution will choose the first 'bar'.

Kenji Hara
December 10, 2013
Am Mon, 09 Dec 2013 23:15:27 -0800
schrieb Jonathan M Davis <jmdavisProg@gmx.com>:

> On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:
> > On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
> > > On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
> > >> I just found weird D behavior about inference of array types.
> > >> 
> > >> Let's suppose we have these overloaded functions:
> > >> 
> > >> import std.stdio;
> > >> 
> > >> void bar(const(int[3]) arr)
> > >> {
> > >> 
> > >>       writeln("static array");
> > >> 
> > >> }
> > >> 
> > >> void bar(const(int[]) arr)
> > >> {
> > >> 
> > >>       writeln("array slice");
> > >> 
> > >> }
> > >> 
> > >> // In main we have something like that:
> > >> int main(string[] args)
> > >> {
> > >> 
> > >>       bar([1,2,3]);
> > >>       writeln(typeof([1,2,3]).stringof);
> > >>       return 0;
> > >> 
> > >> }
> > >> 
> > >> Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3].
> > > 
> > > Array literals are always dynamic arrays. int[3] is a static array.
> > > 
> > > - Jonathan M Davis
> > 
> > The original question is valid then: [1,2,3] goes to the static array overload.
> 
> Then AFAIK, that's a bug. The type of array literals is always a dynamic array, so they should match dynamic array overloads rather than static array overloads, or if they match both due to an implicit conversion, there should be an ambiguity error. Choosing the static array overload over the dynamic one is just plain wrong.
> 
> - Jonathan M Davis
> 

[1,2,3] looks like a static array to me. And if overload
resolution picked the most specialized function it seems
natural to call the int[3] version.
My reasoning being that static arrays can be implicitly
converted to dynamic array, but the reverse is not true. So I
think it would be better to have [1,2,3] be a static array and
keep the current behavoir, no?)

-- 
Marco

December 10, 2013
On Tuesday, December 10, 2013 08:29:02 Kenji Hara wrote:
> On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis
> 
> wrote:
> > On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:
> >> On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
> >> > On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
> >> >> I just found weird D behavior about inference of array types.
> >> >> 
> >> >> Let's suppose we have these overloaded functions:
> >> >> 
> >> >> import std.stdio;
> >> >> 
> >> >> void bar(const(int[3]) arr)
> >> >> {
> >> >> 
> >> >>       writeln("static array");
> >> >> 
> >> >> }
> >> >> 
> >> >> void bar(const(int[]) arr)
> >> >> {
> >> >> 
> >> >>       writeln("array slice");
> >> >> 
> >> >> }
> >> >> 
> >> >> // In main we have something like that:
> >> >> int main(string[] args)
> >> >> {
> >> >> 
> >> >>       bar([1,2,3]);
> >> >>       writeln(typeof([1,2,3]).stringof);
> >> >>       return 0;
> >> >> 
> >> >> }
> >> >> 
> >> >> Weird thing is that the static array version of bar is
> >> >> called,
> >> >> but typeof().stringof is int[], not int[3].
> >> > 
> >> > Array literals are always dynamic arrays. int[3] is a static array.
> >> > 
> >> > - Jonathan M Davis
> >> 
> >> The original question is valid then: [1,2,3] goes to the
> >> static array
> >> overload.
> > 
> > Then AFAIK, that's a bug. The type of array literals is always
> > a dynamic
> > array, so they should match dynamic array overloads rather than
> > static array
> > overloads, or if they match both due to an implicit conversion,
> > there should
> > be an ambiguity error. Choosing the static array overload over
> > the dynamic one
> > is just plain wrong.
> 
> This is an intended behavior. An array literal has dynamic array
> type *by default*.
> But all of literals in D behave as polymorphic.
> 
> char c = 'A';   // character literal has char type by default dchar d = 'A';  // but it may be implicitly typed as wchar/dchar
> 
> string str = "hello";
> dstring dstr = "hello";  // string literal is implicitly typed as
> dstring
> 
> int[] darr = [1,2,3];
> int[3] darr = [1,2,3];   // implicitly typed as int[3]
> 
> So, an array literal [1,2,3] is implicitly convertible both to
> int[] and int[3].
> And, int[3] is more specialized than int[], so overload
> resolution will choose the first 'bar'.

I'd argue that it would be far better to give an ambiguity error rather than silently pick one over the other. In general, having a literal of any kind pick a particular overload when it can match multiple is just begging for trouble.

- Jonathan M Davis

December 10, 2013
Am Tue, 10 Dec 2013 08:29:02 +0100
schrieb "Kenji Hara" <k.hara.pg@gmail.com>:

> This is an intended behavior. An array literal has dynamic array
> type *by default*.
> But all of literals in D behave as polymorphic.
> 
> char c = 'A';   // character literal has char type by default dchar d = 'A';  // but it may be implicitly typed as wchar/dchar
> 
> string str = "hello";
> dstring dstr = "hello";  // string literal is implicitly typed as
> dstring
> 
> int[] darr = [1,2,3];
> int[3] darr = [1,2,3];   // implicitly typed as int[3]
> 
> So, an array literal [1,2,3] is implicitly convertible both to
> int[] and int[3].
> And, int[3] is more specialized than int[], so overload
> resolution will choose the first 'bar'.
> 
> Kenji Hara

So this is how it works. I honestly wouldn't have come up with this. Your example for char makes it clear why this implicit type changing is in place. The OP still has a point though. If they are so polymorphic and "try to specialize" as necessary, then D's typeof(…) must always be in a Schrödinger cat-like state and only decide on an actual result when it is clear from static code analysis that every use of it's argument in the program leads to the same concrete type.

Taking the following example as a failing case for this analysis:

  int[] arr1 = [1,2,3];
  int[3] arr2 = [1,2,3];
  writeln(typeof([1,2,3]).stringof);

It must lead to a compiler error informing the user that [1,2,3] is simultaneously int[] and int[3].

-- 
Marco

December 10, 2013
On Tuesday, 10 December 2013 at 07:46:25 UTC, Jonathan M Davis wrote:
> On Tuesday, December 10, 2013 08:29:02 Kenji Hara wrote:
>> On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis
>> 
>> wrote:
>> > On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:
>> >> On 12/09/2013 10:52 PM, Jonathan M Davis wrote:
>> >> > On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:
>> >> >> I just found weird D behavior about inference of array
>> >> >> types.
>> >> >> 
>> >> >> Let's suppose we have these overloaded functions:
>> >> >> 
>> >> >> import std.stdio;
>> >> >> 
>> >> >> void bar(const(int[3]) arr)
>> >> >> {
>> >> >> 
>> >> >>       writeln("static array");
>> >> >> 
>> >> >> }
>> >> >> 
>> >> >> void bar(const(int[]) arr)
>> >> >> {
>> >> >> 
>> >> >>       writeln("array slice");
>> >> >> 
>> >> >> }
>> >> >> 
>> >> >> // In main we have something like that:
>> >> >> int main(string[] args)
>> >> >> {
>> >> >> 
>> >> >>       bar([1,2,3]);
>> >> >>       writeln(typeof([1,2,3]).stringof);
>> >> >>       return 0;
>> >> >> 
>> >> >> }
>> >> >> 
>> >> >> Weird thing is that the static array version of bar is
>> >> >> called,
>> >> >> but typeof().stringof is int[], not int[3].
>> >> > 
>> >> > Array literals are always dynamic arrays. int[3] is a static
>> >> > array.
>> >> > 
>> >> > - Jonathan M Davis
>> >> 
>> >> The original question is valid then: [1,2,3] goes to the
>> >> static array
>> >> overload.
>> > 
>> > Then AFAIK, that's a bug. The type of array literals is always
>> > a dynamic
>> > array, so they should match dynamic array overloads rather than
>> > static array
>> > overloads, or if they match both due to an implicit conversion,
>> > there should
>> > be an ambiguity error. Choosing the static array overload over
>> > the dynamic one
>> > is just plain wrong.
>> 
>> This is an intended behavior. An array literal has dynamic array
>> type *by default*.
>> But all of literals in D behave as polymorphic.
>> 
>> char c = 'A';   // character literal has char type by default
>> dchar d = 'A';  // but it may be implicitly typed as wchar/dchar
>> 
>> string str = "hello";
>> dstring dstr = "hello";  // string literal is implicitly typed as
>> dstring
>> 
>> int[] darr = [1,2,3];
>> int[3] darr = [1,2,3];   // implicitly typed as int[3]
>> 
>> So, an array literal [1,2,3] is implicitly convertible both to
>> int[] and int[3].
>> And, int[3] is more specialized than int[], so overload
>> resolution will choose the first 'bar'.
>
> I'd argue that it would be far better to give an ambiguity error rather than
> silently pick one over the other. In general, having a literal of any kind
> pick a particular overload when it can match multiple is just begging for
> trouble.
>
> - Jonathan M Davis´
I use this implict converting to static arrays very often and if we deprecate it, we really need something to declare static array literals.
Since [1, 2, 3] is always dynamic we need something like C's {1, 2, 3} (But that would maybe conflict with struct literals).

@Kenji
But eben if [1, 2, 3] is implicit converted to int[3], it is still allocated on the heap, right?
December 10, 2013
On Tuesday, December 10, 2013 09:00:22 Namespace wrote:
> I use this implict converting to static arrays very often and if we deprecate it, we really need something to declare static array literals.

Implicit conversion isn't the problem. It's the fact that there are two possible matches, and it picks one over the other rather than requiring the programmer to indicate which one is correct (e.g. via casting). That's just going to lead to bugs. If there is no conflict, then the implicit conversion is fine. It's just that when there is a conflict that it's a problem.

We have similar problems with stuff like

void foo(bool b) {...}
void foo(long l) {...}

foo(1); //calls the bool overload

There was a huge thread on this a while back where almost no one other than Walter thought that this behavior was good, and it was clearly causing bugs (Walter argued that the solution was to just add an overload for int rather than fixing the conversion problem). IMHO, there should be no implicit conversion of literals when there's a conflict. It should result in an ambiguity error so that the programmer has the opportunity to indicate the correct overload.

- Jonathan M Davis
« First   ‹ Prev
1 2 3 4 5 6 7