digitalmars.D.learn - Type inference and overloaded functions
- FreeSlave (20/20) Dec 09 2013 I just found weird D behavior about inference of array types.
- Jonathan M Davis (3/29) Dec 09 2013 Array literals are always dynamic arrays. int[3] is a static array.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/33) Dec 09 2013 The original question is valid then: [1,2,3] goes to the static array
- Jonathan M Davis (7/48) Dec 09 2013 Then AFAIK, that's a bug. The type of array literals is always a dynamic...
- Kenji Hara (17/72) Dec 09 2013 This is an intended behavior. An array literal has dynamic array
- Jonathan M Davis (6/84) Dec 09 2013 I'd argue that it would be far better to give an ambiguity error rather ...
- Namespace (10/105) Dec 10 2013 I use this implict converting to static arrays very often and if
- Jonathan M Davis (18/21) Dec 10 2013 Implicit conversion isn't the problem. It's the fact that there are two
- Namespace (5/39) Dec 10 2013 Ok.
- Jonathan M Davis (15/17) Dec 10 2013 It should be possible to do that via a templated function which takes a ...
- Namespace (6/30) Dec 10 2013 Ugly. Why not {1, 2, 3} or [1, 2, 3]s. The compiler could (as
- Jonathan M Davis (15/55) Dec 10 2013 Walter and Andrei are very much against adding anything further to the
- Namespace (6/79) Dec 10 2013 scoped waste a lot of space, Typedef is mostly unuseable and
- bearophile (2/5) Dec 10 2013 [1, 2, 3]s seems nice.
- Namespace (3/8) Dec 10 2013 What's with {1, 2, 3}? Should be easy to implement and it's known
- bearophile (4/6) Dec 10 2013 In D {} has plenty of meanings already :-)
- Namespace (2/8) Dec 10 2013 That is no reason against it. ;)
- Namespace (19/25) Dec 10 2013 I've tried it in the last hour and as I thought, with a few
- Namespace (31/37) Dec 10 2013 You was right, it was terrible and so I tried [1, 2, 3]s as
- Namespace (5/45) Dec 10 2013 Would be nice if someone could review it, maybe it's worth to add:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/6) Dec 10 2013 That looks very confusing. The left-hand side looks like a slice, which
- Namespace (6/13) Dec 11 2013 That is intended (but can be discussed of course). It was often
- Chris Cain (7/24) Dec 11 2013 I agree with Ali. arr2 says it's a dynamic array but it's not.
- Namespace (3/28) Dec 11 2013 Ok, I will change that. ;)
- Namespace (42/73) Dec 11 2013 Was a bit tricky but it works now (even if it may not be perfect):
- bearophile (12/38) Dec 11 2013 Very good, this seems a step forward for D. Are you going to
- Namespace (5/52) Dec 11 2013 I'm unsure. I'm not that familiar with dmd at all, so maybe some
- bearophile (16/21) Dec 11 2013 In that code there is both the [$] and the []s syntaxes. So it's
- Namespace (3/24) Dec 11 2013 I'm pretty nervous, but here is the first:
- bearophile (11/13) Dec 11 2013 Good. Keep in mind that at best it will take a month or more for
- Namespace (3/16) Dec 11 2013 Your gig:
- bearophile (24/26) Dec 11 2013 My enhancement request was for the array[$] syntax. The idea of
- Timothee Cour (10/35) Dec 11 2013 yes, that was the prime motivation for DIP34, being able to pass
- bearophile (6/14) Dec 11 2013 It seems Hara has received your message:
- bearophile (44/47) Dec 12 2013 Kenji> Use cast. In real world, if overloaded function takes both
- Namespace (8/8) Dec 12 2013 Why don't you discuss on github?
- bearophile (26/33) Dec 12 2013 I sometimes discuss on GitHub, but when the amount of things I
- Namespace (3/11) Dec 13 2013 Done:
- bearophile (22/24) Dec 17 2013 If you have a situation like this:
- Namespace (4/28) Dec 17 2013 No, not currently. But it is an interesting idea. Maybe I will
- bearophile (11/13) Dec 17 2013 A use case:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/9) Dec 19 2013 Sorry, I can't resist... Golden rule of system programming language
- Kenji Hara (8/42) Dec 12 2013 There's a known issue that the function foo takes the slice of
- Maxim Fomin (3/20) Dec 12 2013 I think there is consensus that in @safe code this should be
- Jonathan M Davis (15/40) Dec 12 2013 Slicing a static array is exactly the same as taking the address of a lo...
- Namespace (26/26) Dec 12 2013 I created a separate branch for the syntax Type[$] and auto[$]:
- bearophile (4/7) Dec 12 2013 It seems a valid use case.
- bearophile (6/6) Dec 12 2013 I presume the situation with this code is not changed by your
- bearophile (6/8) Dec 12 2013 I suggested to support such incomplete literals only with this
- bearophile (7/12) Dec 11 2013 No, the type of the literal is of a fixed-side array, but it gets
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/19) Dec 12 2013 Although important, I wasn't considering that point at all.
- bearophile (4/6) Dec 12 2013 I didn't notice that. It looks strange... I don't understand it.
- Namespace (3/9) Dec 12 2013 I already pointed out why it was that way AND that it's "fixed"
- Kenji Hara (7/13) Dec 10 2013 Why do you think this is possible? If an array literal should
- Jonathan M Davis (19/36) Dec 10 2013 It doesn't need to match only dynamic array types. The problem is when y...
- Marco Leise (13/40) Dec 10 2013 In the case above, *if* there was an int overload would you
- Marco Leise (19/39) Dec 10 2013 So this is how it works. I honestly wouldn't have come up with
- Timon Gehr (13/27) Dec 10 2013 Match with implicit conversion cannot be what is really happening as
- Dicebot (2/5) Dec 10 2013 One of good examples why weakly typed literals suck.
- Marco Leise (15/66) Dec 10 2013 =20
- Kenji Hara (11/18) Dec 10 2013 In early D1 age, array literals and string literals had had
- Marco Leise (7/31) Dec 10 2013 I understand that. The string case probably being the most
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].
Dec 09 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
Dec 09 2013
On 12/09/2013 10:52 PM, Jonathan M Davis wrote:On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:The original question is valid then: [1,2,3] goes to the static array overload. AliI 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
Dec 09 2013
On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote:On 12/09/2013 10:52 PM, Jonathan M Davis wrote: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 DavisOn Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:The original question is valid then: [1,2,3] goes to the static array overload.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
Dec 09 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: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 HaraOn 12/09/2013 10:52 PM, Jonathan M Davis wrote: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.On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:The original question is valid then: [1,2,3] goes to the static array overload.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
Dec 09 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: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 DavisOn Monday, December 09, 2013 22:59:49 Ali Çehreli wrote: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'.On 12/09/2013 10:52 PM, Jonathan M Davis wrote: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.On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:The original question is valid then: [1,2,3] goes to the static array overload.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
Dec 09 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: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?On Tuesday, 10 December 2013 at 07:15:43 UTC, Jonathan M Davis wrote: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´On Monday, December 09, 2013 22:59:49 Ali Çehreli wrote: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'.On 12/09/2013 10:52 PM, Jonathan M Davis wrote: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.On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:The original question is valid then: [1,2,3] goes to the static array overload.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
Dec 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
Dec 10 2013
On Tuesday, 10 December 2013 at 08:26:34 UTC, Jonathan M Davis wrote:On Tuesday, December 10, 2013 09:00:22 Namespace wrote:Ok.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 DavisYeah I remember, but Kenji made a Pull Request to change this. Regardless it would be very useful to have static array literals.
Dec 10 2013
On Tuesday, December 10, 2013 10:10:22 Namespace wrote:Yeah I remember, but Kenji made a Pull Request to change this. Regardless it would be very useful to have static array literals.It should be possible to do that via a templated function which takes a static array and then returns it. e.g. auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]); The compiler should optimize out the heap allocation, since the literal is directly converted to a static array (it might not optimize it now, but it definitely should, in which case, you're effectively creating a static array literal without any heap allocations). Maybe that's more verbose than would be ideal, but it allows us to essentially have static array literals without having to add anything to the language. - Jonathan M Davis
Dec 10 2013
On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote:On Tuesday, December 10, 2013 10:10:22 Namespace wrote:Ugly. Why not {1, 2, 3} or [1, 2, 3]s. The compiler could (as long as necessary) rewrite this to your ugly solution. But library solutions are always ugly and mostly bad and bug prone. See scoped, Typedef and destroy.Yeah I remember, but Kenji made a Pull Request to change this. Regardless it would be very useful to have static array literals.It should be possible to do that via a templated function which takes a static array and then returns it. e.g. auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]); The compiler should optimize out the heap allocation, since the literal is directly converted to a static array (it might not optimize it now, but it definitely should, in which case, you're effectively creating a static array literal without any heap allocations). Maybe that's more verbose than would be ideal, but it allows us to essentially have static array literals without having to add anything to the language. - Jonathan M Davis
Dec 10 2013
On Tuesday, December 10, 2013 10:33:33 Namespace wrote:On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote:Walter and Andrei are very much against adding anything further to the language when it can be done in a library instead. {1, 2, 3} conflicts with C- style struct construction, and while [1, 2, 3]s is nice and short, all it does over staticLiteral([1, 2, 3]) is save some typing, and it requires language changes, whereas it's trivial in comparison to do something like this in a library. In fact, if we were to start over with D now, there would be a number of things that would just be in the library instead of the language (e.g. Andrei has stated several times that new should not have been a keyword and that it should have been handled by the standard library instead of the language). But it's too late for that now, so pretty much all of the stuff that might not end up the language if we were to start over is going to stay. However, that doesn't mean that we're going to be anything more like that in the language when we can do it in the library. - Jonathan M DavisOn Tuesday, December 10, 2013 10:10:22 Namespace wrote:Ugly. Why not {1, 2, 3} or [1, 2, 3]s. The compiler could (as long as necessary) rewrite this to your ugly solution. But library solutions are always ugly and mostly bad and bug prone. See scoped, Typedef and destroy.Yeah I remember, but Kenji made a Pull Request to change this. Regardless it would be very useful to have static array literals.It should be possible to do that via a templated function which takes a static array and then returns it. e.g. auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]); The compiler should optimize out the heap allocation, since the literal is directly converted to a static array (it might not optimize it now, but it definitely should, in which case, you're effectively creating a static array literal without any heap allocations). Maybe that's more verbose than would be ideal, but it allows us to essentially have static array literals without having to add anything to the language. - Jonathan M Davis
Dec 10 2013
On Tuesday, 10 December 2013 at 09:42:50 UTC, Jonathan M Davis wrote:On Tuesday, December 10, 2013 10:33:33 Namespace wrote:scoped waste a lot of space, Typedef is mostly unuseable and destroy is buggy with alias this and doesn't free the space (of course this is intended). I would prefer to do nothing, than a library solution. But let's wait and see. :)On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote:Walter and Andrei are very much against adding anything further to the language when it can be done in a library instead. {1, 2, 3} conflicts with C- style struct construction, and while [1, 2, 3]s is nice and short, all it does over staticLiteral([1, 2, 3]) is save some typing, and it requires language changes, whereas it's trivial in comparison to do something like this in a library. In fact, if we were to start over with D now, there would be a number of things that would just be in the library instead of the language (e.g. Andrei has stated several times that new should not have been a keyword and that it should have been handled by the standard library instead of the language). But it's too late for that now, so pretty much all of the stuff that might not end up the language if we were to start over is going to stay. However, that doesn't mean that we're going to be anything more like that in the language when we can do it in the library. - Jonathan M DavisOn Tuesday, December 10, 2013 10:10:22 Namespace wrote:Ugly. Why not {1, 2, 3} or [1, 2, 3]s. The compiler could (as long as necessary) rewrite this to your ugly solution. But library solutions are always ugly and mostly bad and bug prone. See scoped, Typedef and destroy.Yeah I remember, but Kenji made a Pull Request to change this. Regardless it would be very useful to have static array literals.It should be possible to do that via a templated function which takes a static array and then returns it. e.g. auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]); The compiler should optimize out the heap allocation, since the literal is directly converted to a static array (it might not optimize it now, but it definitely should, in which case, you're effectively creating a static array literal without any heap allocations). Maybe that's more verbose than would be ideal, but it allows us to essentially have static array literals without having to add anything to the language. - Jonathan M Davis
Dec 10 2013
Jonathan M Davis:and while [1, 2, 3]s is nice and short, all it does over staticLiteral([1, 2, 3]) is save some typing, and it requires language changes,[1, 2, 3]s seems nice.
Dec 10 2013
On Tuesday, 10 December 2013 at 12:54:58 UTC, bearophile wrote:Jonathan M Davis:What's with {1, 2, 3}? Should be easy to implement and it's knownand while [1, 2, 3]s is nice and short, all it does over staticLiteral([1, 2, 3]) is save some typing, and it requires language changes,[1, 2, 3]s seems nice.
Dec 10 2013
Namespace:What's with {1, 2, 3}? Should be easy to implement and it'sIn D {} has plenty of meanings already :-) Bye, bearophile
Dec 10 2013
On Tuesday, 10 December 2013 at 14:20:51 UTC, bearophile wrote:Namespace:That is no reason against it. ;)What's with {1, 2, 3}? Should be easy to implement and it'sIn D {} has plenty of meanings already :-) Bye, bearophile
Dec 10 2013
On Tuesday, 10 December 2013 at 14:20:51 UTC, bearophile wrote:Namespace:I've tried it in the last hour and as I thought, with a few changes it is very easy to implement (it needs currently ~30 lines - however my knowledge of the compiler is very limited, so that it could need some more changes). But a short test shows, that something like this is possible with my changes: ---- int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = {1, 2, 3}; assert(is(typeof(arr1) == int[3])); assert(arr1 == [1, 2, 3]); int[] arr2 = {4, 5, 6}; assert(is(typeof(arr2) == int[3])); assert(arr2 == [4, 5, 6]); ---- I like it. :DWhat's with {1, 2, 3}? Should be easy to implement and it'sIn D {} has plenty of meanings already :-) Bye, bearophile
Dec 10 2013
On Tuesday, 10 December 2013 at 14:20:51 UTC, bearophile wrote:Namespace:You was right, it was terrible and so I tried [1, 2, 3]s as syntax. It has cost me hours but now this works pretty well: ---- import std.stdio; void foo(int[3] arr) { assert(is(typeof(arr) == int[3])); } void bar(T)(T arr) { assert(is(T == int[3])); } void main() { int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = [4, 5, 6]s; assert(is(typeof(arr1) == int[3])); assert(arr1 == [4, 5, 6]); int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3])); assert(arr2 == [7, 8, 9]); foo([1, 2, 3]); foo([4, 5, 6]s); bar([44, 55, 66]s); auto arr3 = [111, 222, 333]; assert(is(typeof(arr3) == int[])); auto arr4 = [444, 555, 666]s; assert(is(typeof(arr4) == int[3])); } ----What's with {1, 2, 3}? Should be easy to implement and it'sIn D {} has plenty of meanings already :-) Bye, bearophile
Dec 10 2013
On Wednesday, 11 December 2013 at 00:37:24 UTC, Namespace wrote:On Tuesday, 10 December 2013 at 14:20:51 UTC, bearophile wrote:Would be nice if someone could review it, maybe it's worth to add: Branch: https://github.com/Dgame/dmd/tree/static_array_literals Commit: https://github.com/Dgame/dmd/commit/6296057d919d50b407d4533bab5d2a21fba6230cNamespace:You was right, it was terrible and so I tried [1, 2, 3]s as syntax. It has cost me hours but now this works pretty well: ---- import std.stdio; void foo(int[3] arr) { assert(is(typeof(arr) == int[3])); } void bar(T)(T arr) { assert(is(T == int[3])); } void main() { int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = [4, 5, 6]s; assert(is(typeof(arr1) == int[3])); assert(arr1 == [4, 5, 6]); int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3])); assert(arr2 == [7, 8, 9]); foo([1, 2, 3]); foo([4, 5, 6]s); bar([44, 55, 66]s); auto arr3 = [111, 222, 333]; assert(is(typeof(arr3) == int[])); auto arr4 = [444, 555, 666]s; assert(is(typeof(arr4) == int[3])); } ----What's with {1, 2, 3}? Should be easy to implement and it'sIn D {} has plenty of meanings already :-) Bye, bearophile
Dec 10 2013
On 12/10/2013 04:37 PM, Namespace wrote:int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array? Ali
Dec 10 2013
On Wednesday, 11 December 2013 at 04:01:11 UTC, Ali Çehreli wrote:On 12/10/2013 04:37 PM, Namespace wrote:That is intended (but can be discussed of course). It was often desired to write int[$] arr = [1, 2, 3]; to auto-determine the dimension. And my change does something like that: if you assign a static array to a slice, the dimension is auto-determined and the type is adapted.int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array? Ali
Dec 11 2013
On Wednesday, 11 December 2013 at 09:49:13 UTC, Namespace wrote:On Wednesday, 11 December 2013 at 04:01:11 UTC, Ali Çehreli wrote:I agree with Ali. arr2 says it's a dynamic array but it's not. This could easily lead to errors worse than the class caused by implicit conversions (what's worse than explicitly saying you want an x but getting a y instead?). `int[$]` for this purpose would be acceptable, however. I actually like that idea, personally.On 12/10/2013 04:37 PM, Namespace wrote:That is intended (but can be discussed of course). It was often desired to write int[$] arr = [1, 2, 3]; to auto-determine the dimension. And my change does something like that: if you assign a static array to a slice, the dimension is auto-determined and the type is adapted.int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array? Ali
Dec 11 2013
On Wednesday, 11 December 2013 at 16:28:39 UTC, Chris Cain wrote:On Wednesday, 11 December 2013 at 09:49:13 UTC, Namespace wrote:Ok, I will change that. ;) And I will try to implement the syntax for int[$].On Wednesday, 11 December 2013 at 04:01:11 UTC, Ali Çehreli wrote:I agree with Ali. arr2 says it's a dynamic array but it's not. This could easily lead to errors worse than the class caused by implicit conversions (what's worse than explicitly saying you want an x but getting a y instead?). `int[$]` for this purpose would be acceptable, however. I actually like that idea, personally.On 12/10/2013 04:37 PM, Namespace wrote:That is intended (but can be discussed of course). It was often desired to write int[$] arr = [1, 2, 3]; to auto-determine the dimension. And my change does something like that: if you assign a static array to a slice, the dimension is auto-determined and the type is adapted.int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array? Ali
Dec 11 2013
On Wednesday, 11 December 2013 at 18:31:20 UTC, Namespace wrote:On Wednesday, 11 December 2013 at 16:28:39 UTC, Chris Cain wrote:Was a bit tricky but it works now (even if it may not be perfect): https://github.com/Dgame/dmd/commits/static_array_literals Example: ---- import std.stdio; void foo(int[3] arr) { assert(is(typeof(arr) == int[3])); } void bar(T)(T arr) { assert(is(T == int[3])); } void quatz(int[] arr) { assert(is(typeof(arr) == int[])); } void main() { int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = [4, 5, 6]s; assert(is(typeof(arr1) == int[3])); assert(arr1 == [4, 5, 6]); int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[/*3*/])); assert(arr2 == [7, 8, 9]); int[$] arr_a1 = [54, 74, 90, 2010]; assert(is(typeof(arr_a1) == int[4])); assert(arr_a1 == [54, 74, 90, 2010]); int[$] arr_a2 = [2010, 90, 74, 54]s; assert(is(typeof(arr_a2) == int[4])); assert(arr_a2 == [2010, 90, 74, 54]); foo([1, 2, 3]); foo([4, 5, 6]s); bar([44, 55, 66]s); auto arr3 = [111, 222, 333]; assert(is(typeof(arr3) == int[])); auto arr4 = [444, 555, 666]s; assert(is(typeof(arr4) == int[3])); quatz([3, 2, 1]); quatz([8, 7, 6]s); } ----On Wednesday, 11 December 2013 at 09:49:13 UTC, Namespace wrote:Ok, I will change that. ;) And I will try to implement the syntax for int[$].On Wednesday, 11 December 2013 at 04:01:11 UTC, Ali Çehreli wrote:I agree with Ali. arr2 says it's a dynamic array but it's not. This could easily lead to errors worse than the class caused by implicit conversions (what's worse than explicitly saying you want an x but getting a y instead?). `int[$]` for this purpose would be acceptable, however. I actually like that idea, personally.On 12/10/2013 04:37 PM, Namespace wrote:That is intended (but can be discussed of course). It was often desired to write int[$] arr = [1, 2, 3]; to auto-determine the dimension. And my change does something like that: if you assign a static array to a slice, the dimension is auto-determined and the type is adapted.int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array? Ali
Dec 11 2013
Namespace:void main() { int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = [4, 5, 6]s; assert(is(typeof(arr1) == int[3])); assert(arr1 == [4, 5, 6]); int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[/*3*/])); assert(arr2 == [7, 8, 9]); int[$] arr_a1 = [54, 74, 90, 2010]; assert(is(typeof(arr_a1) == int[4])); assert(arr_a1 == [54, 74, 90, 2010]); int[$] arr_a2 = [2010, 90, 74, 54]s; assert(is(typeof(arr_a2) == int[4])); assert(arr_a2 == [2010, 90, 74, 54]); foo([1, 2, 3]); foo([4, 5, 6]s); bar([44, 55, 66]s); auto arr3 = [111, 222, 333]; assert(is(typeof(arr3) == int[])); auto arr4 = [444, 555, 666]s; assert(is(typeof(arr4) == int[3])); quatz([3, 2, 1]); quatz([8, 7, 6]s); }Very good, this seems a step forward for D. Are you going to create two pull requests for dmd? (it will not be accepted before dmd 2.066). Is it also guarding against this? http://d.puremagic.com/issues/show_bug.cgi?id=3849 That in short is this mistake (this currently doesn't give errors): string[3] a = ["red""green","blue"]; void main() {} Bye, bearophile
Dec 11 2013
On Wednesday, 11 December 2013 at 19:51:24 UTC, bearophile wrote:Namespace:I'm unsure. I'm not that familiar with dmd at all, so maybe some more advanced guy like Kenji should review my code and create an own, better pull. What do you mean?void main() { int[] arr0 = [1, 2, 3]; assert(is(typeof(arr0) == int[])); assert(arr0 == [1, 2, 3]); int[3] arr1 = [4, 5, 6]s; assert(is(typeof(arr1) == int[3])); assert(arr1 == [4, 5, 6]); int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[/*3*/])); assert(arr2 == [7, 8, 9]); int[$] arr_a1 = [54, 74, 90, 2010]; assert(is(typeof(arr_a1) == int[4])); assert(arr_a1 == [54, 74, 90, 2010]); int[$] arr_a2 = [2010, 90, 74, 54]s; assert(is(typeof(arr_a2) == int[4])); assert(arr_a2 == [2010, 90, 74, 54]); foo([1, 2, 3]); foo([4, 5, 6]s); bar([44, 55, 66]s); auto arr3 = [111, 222, 333]; assert(is(typeof(arr3) == int[])); auto arr4 = [444, 555, 666]s; assert(is(typeof(arr4) == int[3])); quatz([3, 2, 1]); quatz([8, 7, 6]s); }Very good, this seems a step forward for D. Are you going to create two pull requests for dmd? (it will not be accepted before dmd 2.066).Is it also guarding against this? http://d.puremagic.com/issues/show_bug.cgi?id=3849 That in short is this mistake (this currently doesn't give errors): string[3] a = ["red""green","blue"]; void main() {} Bye, bearophileNot yet tested, but I will. :)
Dec 11 2013
Namespace:I'm unsure. I'm not that familiar with dmd at all, so maybe some more advanced guy like Kenji should review my code and create an own, better pull.In that code there is both the [$] and the []s syntaxes. So it's better to submit them as two separated pull requests for the D front-end. Lately Kenji seems a little less active, but he will probably be glad to review your code, fix it, etc.What do you mean?Walter said that dmd 2.065 is meant only as bug-fix release (expecially ICEs) so no "significant" language enhancement requests will be added in dmd 2.065, and they have to wait for dmd 2.066. But dmd 2.065 is supposed to end quicker, so we will not wait a lot of time.Not yet tested, but I will. :)(Issue 3849 also suggests the "..." syntax inside array literals to fulfill a narrow corner case that Walter seems to appreciate. I think it's not an important syntax.) Bye, bearophile
Dec 11 2013
On Wednesday, 11 December 2013 at 20:50:01 UTC, bearophile wrote:Namespace:I'm pretty nervous, but here is the first: https://github.com/D-Programming-Language/dmd/pull/2952I'm unsure. I'm not that familiar with dmd at all, so maybe some more advanced guy like Kenji should review my code and create an own, better pull.In that code there is both the [$] and the []s syntaxes. So it's better to submit them as two separated pull requests for the D front-end. Lately Kenji seems a little less active, but he will probably be glad to review your code, fix it, etc.What do you mean?Walter said that dmd 2.065 is meant only as bug-fix release (expecially ICEs) so no "significant" language enhancement requests will be added in dmd 2.065, and they have to wait for dmd 2.066. But dmd 2.065 is supposed to end quicker, so we will not wait a lot of time.Not yet tested, but I will. :)(Issue 3849 also suggests the "..." syntax inside array literals to fulfill a narrow corner case that Walter seems to appreciate. I think it's not an important syntax.) Bye, bearophile
Dec 11 2013
Namespace:I'm pretty nervous, but here is the first: https://github.com/D-Programming-Language/dmd/pull/2952Good. Keep in mind that at best it will take a month or more for your patch to be accepted. Also patches that implement basic language features like this pass a stringent process of review, that can be laborious and a bit painful. And even after after all that work there's a certain probability of rejection. So you have to build stamina and accumulate patience :-) (Other kind of patches, like D front-end bug fixes or Phobos improvements are faster and often much less painful). Bye, bearophile
Dec 11 2013
On Wednesday, 11 December 2013 at 23:20:30 UTC, bearophile wrote:Namespace:Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045I'm pretty nervous, but here is the first: https://github.com/D-Programming-Language/dmd/pull/2952Good. Keep in mind that at best it will take a month or more for your patch to be accepted. Also patches that implement basic language features like this pass a stringent process of review, that can be laborious and a bit painful. And even after after all that work there's a certain probability of rejection. So you have to build stamina and accumulate patience :-) (Other kind of patches, like D front-end bug fixes or Phobos improvements are faster and often much less painful). Bye, bearophile
Dec 11 2013
Namespace:Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045My enhancement request was for the array[$] syntax. The idea of []s was invented by someone else (Timothee Cour?). I like the practical comments by Hara. If Kenji thinks the []s is not useful for efficiency (because the efficiency can be obtained with just improvements of the compiler), then the []s syntax becomes less necessary. On the other hand this is an interesting use case that compiler improvements alone could not be enough to allow: void fun(int[3]) {} void main() { int[3] x = [1, 2, 3]; fun(x); // OK fun([1, 2, 3]); // error fun([1, 2, 3]s); // OK } Are vector ops supported? int[6] a; a = [1,2,3]s[] + [4,5,6]s[]; DIP34 is still a draft, and it shows, some corner cases are missing in that document and need to be found, fleshed out and added to the DIP34. Bye, bearophile
Dec 11 2013
On Wed, Dec 11, 2013 at 5:17 PM, bearophile <bearophileHUGS lycos.com>wrote:Namespace: Your gig: https://github.com/D-Programming-Language/dmd/pull/yes, that was the prime motivation for DIP34, being able to pass un-ambiguously a static array to a function without having to declare an intermediate variable first. when fun() has overloads for both static and non-static arrays (or is just declared as fun(T)(T a) ), the compiler cannot guess whether fun([1,2,3]) asks for static or dynamic array, and probably has to assume dynamic array. And int[$] would require declaring a variable before passing it, eg: int[$]x=[1,2,3]. With [1,2,3]s, there is no ambiguity.2952#discussion_r8288045My enhancement request was for the array[$] syntax. The idea of []s was invented by someone else (Timothee Cour?). I like the practical comments by Hara. If Kenji thinks the []s is not useful for efficiency (because the efficiency can be obtained with just improvements of the compiler), then the []s syntax becomes less necessary. On the other hand this is an interesting use case that compiler improvements alone could not be enough to allow: void fun(int[3]) {} void main() { int[3] x = [1, 2, 3]; fun(x); // OK fun([1, 2, 3]); // error fun([1, 2, 3]s); // OK }Are vector ops supported? int[6] a; a = [1,2,3]s[] + [4,5,6]s[]; DIP34 is still a draft, and it shows, some corner cases are missing in that document and need to be found, fleshed out and added to the DIP34. Bye, bearophile
Dec 11 2013
Timothee Cour:Sorry, there's no error there.void fun(int[3]) {} void main() { int[3] x = [1, 2, 3]; fun(x); // OK fun([1, 2, 3]); // error fun([1, 2, 3]s); // OK }yes, that was the prime motivation for DIP34,It seems Hara has received your message: https://d.puremagic.com/issues/show_bug.cgi?id=8903#c7 Bye, bearophile
Dec 11 2013
Namespace:Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045This is part of the thread there:Kenji> Use cast. In real world, if overloaded function takes both int[] and int[3], normally int[3] version would provide specialized implementation for 3 length arrays (eg. unroll the loop to operate each elements of the given array). Therefore force to invoke int[] version with array literal is not usual situation. Cast will fit in such case.< If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); } DMD generates: __Dmain comdat L0: push EBX mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ push 3 push EAX call near ptr __d_arrayliteralTX mov EBX,EAX mov dword ptr [EAX],1 xor EAX,EAX mov dword ptr 4[EBX],2 mov dword ptr 8[EBX],3 add ESP,8 pop EBX ret With the []s syntax it should become: void foo(int[]) {} void main() { foo([1, 2, 3]); foo([4, 5, 6]s); } But I don't know how much common is such need. In the Rust language when you write an array literal you always prefix it with a symbol, to tell the compiler where you want to allocate it. So I think it's not so useless :-) Bye, bearophileFurhtermore, what if we indeed want to pass a dynamic array ?<<
Dec 12 2013
Why don't you discuss on github? And finally I did it: ---- auto[$] a_arr2 = dyn_arr[4 .. 8]; assert(is(typeof(a_arr2) == int[4])); ---- I will make a Pull Request tomorrow. Hope my code isn't that bad. :/
Dec 12 2013
Namespace:Why don't you discuss on github?I sometimes discuss on GitHub, but when the amount of things I have to say are large enough I think a forum like this is better. Also I don't like the lack of threading in GitHub comments.And finally I did it: ---- auto[$] a_arr2 = dyn_arr[4 .. 8]; assert(is(typeof(a_arr2) == int[4])); ---- I will make a Pull Request tomorrow.Good :-) ------------------ Regarding fixed sized arrays there's another point, visible here: void main() { int[3] a, b, c; pragma(msg, typeof(a[] + b[])); } It prints: int[] So it seems the compiler loses track of the compile-time knowledge of the length of those arrays (it's probably caused by the slicing). In my opinion this is quite important because such loss of information makes it harder for the compiler to rewrite code as "c[] = a[] + b[]" as: foreach (immutable i; 0 .. 3) c[i] = a[i] + b[i]; That later the back-end should unroll in just three sums (this is routinely done by the Fortran array ops); and a smart back-end can even rewrite with a single SIMD instruction (adding padding to the a, b, and c arrays making them 4 integers long). Bye, bearophile
Dec 12 2013
On Friday, 13 December 2013 at 00:37:36 UTC, Namespace wrote:Why don't you discuss on github? And finally I did it: ---- auto[$] a_arr2 = dyn_arr[4 .. 8]; assert(is(typeof(a_arr2) == int[4])); ---- I will make a Pull Request tomorrow. Hope my code isn't that bad. :/Done: https://github.com/D-Programming-Language/dmd/pull/2958
Dec 13 2013
Namespace:Done: https://github.com/D-Programming-Language/dmd/pull/2958If you have a situation like this: int[3] foo() { typeof(return) a; return a; } void main() { int[100] b; b[0 .. 3] = foo(); } Can you use code like this to infer the length of the part needed to copy? int[3] foo() { typeof(return) a; return a; } void main() { int[100] b; b[0 .. $] = foo(); } Bye, bearophile
Dec 17 2013
On Tuesday, 17 December 2013 at 17:01:55 UTC, bearophile wrote:Namespace:No, not currently. But it is an interesting idea. Maybe I will implement this. And as far as I have enough time, I will also add test cases. Maybe on christmas. :)Done: https://github.com/D-Programming-Language/dmd/pull/2958If you have a situation like this: int[3] foo() { typeof(return) a; return a; } void main() { int[100] b; b[0 .. 3] = foo(); } Can you use code like this to infer the length of the part needed to copy? int[3] foo() { typeof(return) a; return a; } void main() { int[100] b; b[0 .. $] = foo(); } Bye, bearophile
Dec 17 2013
Namespace:No, not currently. But it is an interesting idea. Maybe I will implement this.A use case: https://d.puremagic.com/issues/show_bug.cgi?id=11757#c3 Visible in this line: key2[0 .. digestSize] = key.md5Of; But my suggested syntax is not that good, here $ has already a meaning, that is the whole length of b, So some different idea is needed here :-( b[0 .. $] = foo(); Otherwise you have to write code like: b[0 .. ReturnType!foo.length] = foo();
Dec 17 2013
On 12/17/2013 07:21 PM, bearophile wrote:But my suggested syntax is not that good, here $ has already a meaning, that is the whole length of b, So some different idea is needed here :-( b[0 .. $] = foo();Sorry, I can't resist... Golden rule of system programming language syntax: When in doubt, reach for static: b[0 .. $tatic] = foo(); Done! :p Ali
Dec 19 2013
On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:Namespace:There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in safe code.Your gig: https://github.com/D-Programming-Language/dmd/pull/2952#discussion_r8288045This is part of the thread there:Kenji> Use cast. In real world, if overloaded function takes both int[] and int[3], normally int[3] version would provide specialized implementation for 3 length arrays (eg. unroll the loop to operate each elements of the given array). Therefore force to invoke int[] version with array literal is not usual situation. Cast will fit in such case.< If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); }Furhtermore, what if we indeed want to pass a dynamic array ?<<With the []s syntax it should become: void foo(int[]) {} void main() { foo([1, 2, 3]); foo([4, 5, 6]s); } But I don't know how much common is such need. In the Rust language when you write an array literal you always prefix it with a symbol, to tell the compiler where you want to allocate it. So I think it's not so useless :-) Bye, bearophileI'm afraid that allowing foo([4, 5, 6]s) would easily cause memory corruption. I don't want to hurt language future by the trivial syntactic sugar. Kenji Hara
Dec 12 2013
On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote:On Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:I think there is consensus that in safe code this should be blocked.If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); }There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in safe code. Kenji Hara
Dec 12 2013
On Friday, December 13, 2013 07:19:50 Maxim Fomin wrote:On Friday, 13 December 2013 at 04:13:04 UTC, Kenji Hara wrote:Slicing a static array is exactly the same as taking the address of a local variable, except that you then have a length in addition to the address. If that slice is assigned to anything which has a lifetime greater than that of the static array that was sliced, then the slice will be referring to invalid memory. That's clearly system, and I don't see how anyone could even argue otherwise. Yes, there is plenty of code which is currently considered safe by the compiler which will break once slicing a static array is considered system like it needs to be (especially because static arrays are unfortunately automatically sliced when they're passed to a function which takes a dynamic array - I really wish that that were'n the case), but that can't be avoided. So, yes, changing it so that slicing a static array is system will cause annoying code breakage, but I don't see any way around it without breaking what safe means and does. - Jonathan M DavisOn Thursday, 12 December 2013 at 18:20:25 UTC, bearophile wrote:I think there is consensus that in safe code this should be blocked.If I have a function foo that takes a slice as input, and I want to pass it two arrays, the first time allocated on the heap and the second on the stack, I have to use an auxiliary variable: void foo(int[]) {} void main() { foo([1, 2, 3]); int[3] tmp = [4, 5, 6]; foo(tmp); }There's a known issue that the function foo takes the slice of stack allocated data. Today some peoples argue that it is unsafe operation and should be disallowed in safe code. Kenji Hara
Dec 12 2013
I created a separate branch for the syntax Type[$] and auto[$]: https://github.com/Dgame/dmd/commit/438a519d28d1683086083e673b2630a64c269f5f Example: ---- int[$] arr_a1 = [54, 74, 90, 2010]; assert(is(typeof(arr_a1) == int[4])); assert(arr_a1 == [54, 74, 90, 2010]); int[$] arr_a2 = [2010, 90, 74, 54]; assert(is(typeof(arr_a2) == int[4])); assert(arr_a2 == [2010, 90, 74, 54]); int[] dyn_arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; int[$] stat_arr = dyn_arr[3 .. 6]; assert(is(typeof(stat_arr) == int[3])); auto[$] a_arr1 = [1, 2, 3]; assert(is(typeof(a_arr1) == int[3])); auto[$] a_arr2 = dyn_arr[4 .. 8]; /// Sadly not possible for me //int s = 2, e = 7; //int[$] stat_arr2 = dyn_arr[s .. e]; /// fails //int[$] stat_arr3 = dyn_arr[]; /// fails ---- Sadly I don't know how I could deduce the type of: ---- auto[$] a_arr2 = dyn_arr[4 .. 8]; /// Sadly not possible for me ---- I will try this again before I open a pull request. Maybe some of you know how to do this?
Dec 12 2013
Namespace:Sadly I don't know how I could deduce the type of: ---- auto[$] a_arr2 = dyn_arr[4 .. 8]; /// Sadly not possible for meIt seems a valid use case. Bye, bearophile
Dec 12 2013
I presume the situation with this code is not changed by your patches: string[3] a = ["red""green","blue"]; void main() {} Bye, bearophile
Dec 12 2013
string[3] a = ["red""green","blue"]; void main() {}I suggested to support such incomplete literals only with this extra syntax: int[3] a = [1, 2, ...]; void main() {} Bye, bearophile
Dec 12 2013
Ali Çehreli:No, the type of the literal is of a fixed-side array, but it gets assigned to a dynamic array, so it's a slice. I am not sure but I Think arr2 data is allocated on the stack. It looks a little confusing, but I think it contains a rule we can learn. Bye, bearophileint[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array?
Dec 11 2013
On 12/11/2013 05:09 PM, bearophile wrote:Ali Çehreli:No problem there.No, the type of the literal is of a fixed-side array, but it gets assigned to a dynamic array, so it's a slice.int[] arr2 = [7, 8, 9]s; assert(is(typeof(arr2) == int[3]));That looks very confusing. The left-hand side looks like a slice, which I can append elements to but its type is a static array?I am not sure but I Think arr2 data is allocated on the stack.Although important, I wasn't considering that point at all.It looks a little confusing, but I think it contains a rule we can learn.But look at the assertion: the type of the *slice* arr2 is int[3]. :)Bye, bearophileAli
Dec 12 2013
Ali Çehreli:But look at the assertion: the type of the *slice* arr2 is int[3]. :)I didn't notice that. It looks strange... I don't understand it. Bye, bearophile
Dec 12 2013
On Thursday, 12 December 2013 at 15:35:52 UTC, bearophile wrote:Ali Çehreli:I already pointed out why it was that way AND that it's "fixed" now. ;)But look at the assertion: the type of the *slice* arr2 is int[3]. :)I didn't notice that. It looks strange... I don't understand it. Bye, bearophile
Dec 12 2013
On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote:On Tuesday, December 10, 2013 10:10:22 Namespace wrote: auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]);Why do you think this is possible? If an array literal should match _only_ dynamic array types, it would never work. Because compiler will try to match array literal to static array T[n]. The feature which I have described is working here. Kenji Hara
Dec 10 2013
On Tuesday, December 10, 2013 11:19:45 Kenji Hara wrote:On Tuesday, 10 December 2013 at 09:28:27 UTC, Jonathan M Davis wrote:It doesn't need to match only dynamic array types. The problem is when you have an overload. e.g. auto foo(T[] arr) {...} auto foo(T[3] arr) {...} foo([1, 2, 3]); Silently selecting one of the two is bug-prone - especially if it's the static one that gets selected, as in most cases, it would be the dynamic one which matches. Having dynamic array literals implicitly convert to static arrays when they're assigned to static arrays makes sense when there's no ambiguity. And in general, something like staticLiteral should be unnecessary when passing to a function, as the array literal would be treated as a dynamic array or a static array depending on the function's parameters, but it could be useful in cases where you want to be explicit about the type or when using auto. And it may not be worth adding a function such as staticLiteral, but I think that it's better than trying to add static array literals to the language, particularly since we're trying to avoid adding features to the language when they can be implemented in the standard library instead. - Jonathan M DavisOn Tuesday, December 10, 2013 10:10:22 Namespace wrote: auto staticLiteral(T, size_t n)(T[n] literal) { return literal; } auto staticArray = staticLiteral([1, 2, 3, 4]);Why do you think this is possible? If an array literal should match _only_ dynamic array types, it would never work. Because compiler will try to match array literal to static array T[n]. The feature which I have described is working here.
Dec 10 2013
Am Tue, 10 Dec 2013 00:26:22 -0800 schrieb Jonathan M Davis <jmdavisProg gmx.com>:On Tuesday, December 10, 2013 09:00:22 Namespace wrote:In the case above, *if* there was an int overload would you argue for still requiring to use foo(cast(int)1) ? Since that is what would come out of it when cast(int[3])[1,2,3] is required. That would hurt the readability of I/O functions that are specialized for all integral types. EndianStream comes to mind. e.g.: stream.write(cast(int)1); Since cast is a blunt tool, I expect APIs to change away from overloads entirely and use writeInt, writeUbyte etc. instead. -- MarcoI 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
Dec 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=20 type *by default*. But all of literals in D behave as polymorphic. =20 char c =3D 'A'; // character literal has char type by default dchar d =3D 'A'; // but it may be implicitly typed as wchar/dchar =20 string str =3D "hello"; dstring dstr =3D "hello"; // string literal is implicitly typed as=20 dstring =20 int[] darr =3D [1,2,3]; int[3] darr =3D [1,2,3]; // implicitly typed as int[3] =20 So, an array literal [1,2,3] is implicitly convertible both to=20 int[] and int[3]. And, int[3] is more specialized than int[], so overload=20 resolution will choose the first 'bar'. =20 Kenji HaraSo 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(=E2=80=A6) must always be in a Schr=C3=B6dinger 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 =3D [1,2,3]; int[3] arr2 =3D [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]. --=20 Marco
Dec 10 2013
On 12/10/2013 08:29 AM, Kenji Hara wrote: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 HaraMatch with implicit conversion cannot be what is really happening as otherwise the following call would be ambiguous: int bar(int[3] arr){ return 1; } int bar(double[] arr){ return 2; } int bar(int[] arr){ return 3; } static assert(bar([1,2,3])==1);
Dec 10 2013
On Tuesday, 10 December 2013 at 07:29:03 UTC, Kenji Hara wrote:This is an intended behavior. An array literal has dynamic array type *by default*. But all of literals in D behave as polymorphic.One of good examples why weakly typed literals suck.
Dec 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 =C3=87ehreli wrote:=20On 12/09/2013 10:52 PM, Jonathan M Davis wrote:=20 Then AFAIK, that's a bug. The type of array literals is always a dynamic=On Tuesday, December 10, 2013 07:47:38 FreeSlave wrote:=20 The original question is valid then: [1,2,3] goes to the static array overload.I just found weird D behavior about inference of array types. =20 Let's suppose we have these overloaded functions: =20 import std.stdio; =20 void bar(const(int[3]) arr) { =20 writeln("static array"); =20 } =20 void bar(const(int[]) arr) { =20 writeln("array slice"); =20 } =20 // In main we have something like that: int main(string[] args) { =20 bar([1,2,3]); writeln(typeof([1,2,3]).stringof); return 0; =20 } =20 Weird thing is that the static array version of bar is called, but typeof().stringof is int[], not int[3].=20 Array literals are always dynamic arrays. int[3] is a static array. =20 - Jonathan M Davisarray, so they should match dynamic array overloads rather than static ar=ray=20overloads, or if they match both due to an implicit conversion, there sho=uld=20be an ambiguity error. Choosing the static array overload over the dynami=c one=20is just plain wrong. =20 - Jonathan M Davis =20[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?) --=20 Marco
Dec 10 2013
On Tuesday, 10 December 2013 at 07:32:08 UTC, Marco Leise wrote:[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?)In early D1 age, array literals and string literals had had static array types which corresponding to the literals' element count. However it had caused template code bloat. void foo(T)(T arg) { ... } foo("aaa"); // instantiate foo!(char[3]) foo("bbbb"); // instantiate foo!(char[4]) foo([1,2]); // instantiate foo!(int[2]) foo([1,2,3]); // instantiate foo!(int[3]) So their types were changed to dynamic array by default. Kenji Hara
Dec 10 2013
Am Tue, 10 Dec 2013 11:56:40 +0100 schrieb "Kenji Hara" <k.hara.pg gmail.com>:On Tuesday, 10 December 2013 at 07:32:08 UTC, Marco Leise wrote:I understand that. The string case probably being the most heavy weight one that prompted the change. Damn, compilers are complicated. -- Marco[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?)In early D1 age, array literals and string literals had had static array types which corresponding to the literals' element count. However it had caused template code bloat. void foo(T)(T arg) { ... } foo("aaa"); // instantiate foo!(char[3]) foo("bbbb"); // instantiate foo!(char[4]) foo([1,2]); // instantiate foo!(int[2]) foo([1,2,3]); // instantiate foo!(int[3]) So their types were changed to dynamic array by default. Kenji Hara
Dec 10 2013