www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - dmd 1.057 and 2.041 release

reply Walter Bright <newshound1 digitalmars.com> writes:
Lots of meat and potatoes here, and a cookie! (spelling checker for 
error messages)

http://www.digitalmars.com/d/1.0/changelog.html
http://ftp.digitalmars.com/dmd.1.057.zip


http://www.digitalmars.com/d/2.0/changelog.html
http://ftp.digitalmars.com/dmd.2.041.zip

Thanks to the many people who contributed to this update!
Mar 07 2010
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Thanks! A pleasant surprise to see interface contracts.
Mar 07 2010
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
This is great, thank you! I'm especially looking forward to playing with the new operator overloading method. :) -Lars
Mar 08 2010
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Walter Bright <newshound1 digitalmars.com> wrote:

 Lots of meat and potatoes here, and a cookie! (spelling checker for  
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
I don't know what to find more awesome with this update - possibly the operator overloading. Thanks a bunch, guys! -- Simen
Mar 08 2010
parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Simen kjaeraas wrote:
 Walter Bright <newshound1 digitalmars.com> wrote:
 
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
I don't know what to find more awesome with this update - possibly the operator overloading. Thanks a bunch, guys!
I just noticed that Steven Schveighoffer's array append patch made it into this release. That ranks pretty high on the awesome scale too. :) -Lars
Mar 08 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 03:45:21 -0500, Lars T. Kyllingstad  
<public kyllingen.nospamnet> wrote:

 Simen kjaeraas wrote:
 Walter Bright <newshound1 digitalmars.com> wrote:

 Lots of meat and potatoes here, and a cookie! (spelling checker for  
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
I don't know what to find more awesome with this update - possibly the operator overloading. Thanks a bunch, guys!
I just noticed that Steven Schveighoffer's array append patch made it into this release. That ranks pretty high on the awesome scale too. :)
Thanks :) One note that was not mentioned on the changelog, there are three new runtime functions for arrays. They are in object.di (and the docs are there too): * setCapacity(T[] arr, int newcapacity): preallocate at least newcapacity elements. This is intended to replace the "set length to zero" trick. * property capacity(T[] arr): get the capacity (yes, it's a property, ddoc does not propogate the property attribute) * shrinkToFit(T[] arr): This one is a bit tricky and technically unsafe. It reduces the size of the "allocated" length to fit the length of the array. The allocated length is the length that the runtime assumes is being used of the memory block. This is what aids in preventing stomping, so use with care. You can achieve stomping if you use shrinkToFit on a slice, but still have references to the trimmed data. Example: string s = "12345".idup; string slice = s[0..2]; slice.shrinkToFit(); // tells the runtime that you will no longer use any data beyond the slice slice ~= "00"; // appends in place, overwriting immutable data referenced in s! Using s after such usage results in undefined behavior (probably should be noted in the docs). The use case is when you want to reuse a buffer when you know you will not use the trimmed area again. You can consider the trimmed off data unallocated. The shrinkToFit name is not my favorite, anyone care to submit a better name? minimize is out because it has connotations of math already. setCapacity will be changed in the next release to reserve() (could not squeeze that change in), since it was pointed out that you are requesting a capacity, not setting it. -Steve
Mar 08 2010
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Mar 8, 2010 at 14:22, Steven Schveighoffer <schveiguy yahoo.com>wrote:

 The shrinkToFit name is not my favorite, anyone care to submit a better
 name?  minimize is out because it has connotations of math already.
minCapacity minimizeCapacity shrinkCapacity shrink (just shrink) releaseCapacity compacify fitCapacity minFit??? reduceToFit contract minify adjust Philippe
Mar 08 2010
parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 08 Mar 2010 16:42:54 -0500, Philippe Sigaud  
<philippe.sigaud gmail.com> wrote:

 On Mon, Mar 8, 2010 at 14:22, Steven Schveighoffer  
 <schveiguy yahoo.com>wrote:

 The shrinkToFit name is not my favorite, anyone care to submit a better
 name?  minimize is out because it has connotations of math already.
minCapacity minimizeCapacity shrinkCapacity shrink (just shrink) releaseCapacity compacify fitCapacity minFit??? reduceToFit contract minify adjust Philippe
compact
Mar 08 2010
parent reply grauzone <none example.net> writes:
Robert Jacques wrote:
 On Mon, 08 Mar 2010 16:42:54 -0500, Philippe Sigaud 
 <philippe.sigaud gmail.com> wrote:
 
 On Mon, Mar 8, 2010 at 14:22, Steven Schveighoffer 
 <schveiguy yahoo.com>wrote:

 The shrinkToFit name is not my favorite, anyone care to submit a better
 name?  minimize is out because it has connotations of math already.
minCapacity minimizeCapacity shrinkCapacity shrink (just shrink) releaseCapacity compacify fitCapacity minFit??? reduceToFit contract minify adjust Philippe
compact
Many of these names (including shrinkToFit) suggest that memory usage is reduced by freeing the left over memory after the array. This is not true: the function just enables stomping of the memory past the slice passed to the function. It's a very specialized and dangerous function (but still may be critical for good performance), and maybe it should rather have a more convoluted/long name than a simple one.
Mar 09 2010
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Mar 9, 2010 at 11:29, grauzone <none example.net> wrote:

 Many of these names (including shrinkToFit) suggest that memory usage is
 reduced by freeing the left over memory after the array. This is not true:
 the function just enables stomping of the memory past the slice passed to
 the function.

 It's a very specialized and dangerous function (but still may be critical
 for good performance), and maybe it should rather have a more
 convoluted/long name than a simple one.
enableStomping? recycle? Anyway IANANES (I'm not a native English speaker), so I'll let Steven decide. Philippe
Mar 09 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Philippe Sigaud" <philippe.sigaud gmail.com> wrote in message 
news:mailman.119.1268166534.4461.digitalmars-d-announce puremagic.com...
 On Tue, Mar 9, 2010 at 11:29, grauzone <none example.net> wrote:

 Many of these names (including shrinkToFit) suggest that memory usage is
 reduced by freeing the left over memory after the array. This is not 
 true:
 the function just enables stomping of the memory past the slice passed to
 the function.

 It's a very specialized and dangerous function (but still may be critical
 for good performance), and maybe it should rather have a more
 convoluted/long name than a simple one.
enableStomping?
placeUnderFoot?
Mar 09 2010
parent Bernard Helyer <b.helyer gmail.com> writes:
On 10/03/10 11:06, Nick Sabalausky wrote:
 "Philippe Sigaud"<philippe.sigaud gmail.com>  wrote in message
 news:mailman.119.1268166534.4461.digitalmars-d-announce puremagic.com...
 enableStomping?
placeUnderFoot?
greekWedding?
Mar 10 2010
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
It seems array literals have become dynamic arrays, but I can't find any mention of that in the change log. pragma(msg, typeof([1,2,3]).stringof); // Prints "int[3u]" with DMD 2.040 // Prints "int[]" with DMD 2.041 -Lars
Mar 08 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Lars T. Kyllingstad wrote:
 It seems array literals have become dynamic arrays, but I can't find any 
 mention of that in the change log.
I'll fix.
Mar 13 2010
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 08 Mar 2010 09:54:12 +0300, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Lots of meat and potatoes here, and a cookie! (spelling checker for  
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
Thank! BTW, 2.0 changelog page is messed up again
Mar 08 2010
prev sibling next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
bearophile must be very happy :-) - Add !in operator. - opCast(bool) and implicit call in if But I don't like this: "This only happens, however, for instances of structs. Class references are converted to bool by checking to see if the class reference is null or not." When I do: if (x) { } I'm normally interested to enter the if branch if x is not null and it has an interesting value. For example, if I implement a String class I would implement it as not being empty. But I think the biggest problem is making a different semantic for this to structs and classes. You'll have programmers wondering why the if branch was entered even if my class implemented opBool not to enter it. But time will tell. For opCast maybe it would be better to have some examples, like: T opCast(T)() if (is(T == bool)) { } T opCast(T)() if (is(T == int)) { } (it's not very intuitive that I have to do that to implement opCast, it's different from the other operator overloading that rely on strings) But very cool that opCast to many different types is implemented! :-)
Mar 08 2010
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Ary Borenszweig wrote:
 Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
bearophile must be very happy :-) - Add !in operator. - opCast(bool) and implicit call in if But I don't like this: "This only happens, however, for instances of structs. Class references are converted to bool by checking to see if the class reference is null or not." When I do: if (x) { } I'm normally interested to enter the if branch if x is not null and it has an interesting value. For example, if I implement a String class I would implement it as not being empty. But I think the biggest problem is making a different semantic for this to structs and classes. You'll have programmers wondering why the if branch was entered even if my class implemented opBool not to enter it. But time will tell. For opCast maybe it would be better to have some examples, like: T opCast(T)() if (is(T == bool)) { } T opCast(T)() if (is(T == int)) { } (it's not very intuitive that I have to do that to implement opCast, it's different from the other operator overloading that rely on strings) But very cool that opCast to many different types is implemented! :-)
And isn't it better for the spellchecker to show the closest match using levenshtein distance instead of just distance 1?
Mar 08 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:
 And isn't it better for the spellchecker to show the closest match using 
 levenshtein distance instead of just distance 1?
Walter is an engineer, and follows the KISS principle, he likes to use the simpler thing that can possibly work (especially in the first version of something). I think the current spellchecker can be good enough. Bye, bearophile
Mar 08 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:
 I'm normally interested to enter the if branch if x is not null and it 
 has an interesting value. For example, if I implement a String class I 
 would implement it as not being empty. But I think the biggest problem 
 is making a different semantic for this to structs and classes. You'll 
 have programmers wondering why the if branch was entered even if my 
 class implemented opBool not to enter it. But time will tell.
A solution can be to disallow opCast!(bool) in classes. So when in your code you convert a struct (that already defines opCast!(bool)) to a class, or when you try to add opCast!(bool) to a class, the compiler gives you a nice compilation error, and saves you from possible bugs. A warning too can be better than nothing.
 For opCast maybe it would be better to have some examples, like:
 
 T opCast(T)() if (is(T == bool)) {
 }
 
 T opCast(T)() if (is(T == int)) {
 }
 
 (it's not very intuitive that I have to do that to implement opCast, 
 it's different from the other operator overloading that rely on strings)
This works: import std.stdio: writeln; struct Foo { int len; this(int x) { this.len = x; } T opCast(T:bool)() { return this.len != 0; } T opCast(T:int)() { return this.len; } } void main() { auto f = Foo(5); if (f) writeln("true"); else writeln("false"); writeln(cast(int)f); } Bye, bearophile
Mar 08 2010
parent Ary Borenszweig <ary esperanto.org.ar> writes:
bearophile wrote:
 Ary Borenszweig:
 I'm normally interested to enter the if branch if x is not null and it 
 has an interesting value. For example, if I implement a String class I 
 would implement it as not being empty. But I think the biggest problem 
 is making a different semantic for this to structs and classes. You'll 
 have programmers wondering why the if branch was entered even if my 
 class implemented opBool not to enter it. But time will tell.
A solution can be to disallow opCast!(bool) in classes. So when in your code you convert a struct (that already defines opCast!(bool)) to a class, or when you try to add opCast!(bool) to a class, the compiler gives you a nice compilation error, and saves you from possible bugs. A warning too can be better than nothing.
 For opCast maybe it would be better to have some examples, like:

 T opCast(T)() if (is(T == bool)) {
 }

 T opCast(T)() if (is(T == int)) {
 }

 (it's not very intuitive that I have to do that to implement opCast, 
 it's different from the other operator overloading that rely on strings)
This works: import std.stdio: writeln; struct Foo { int len; this(int x) { this.len = x; } T opCast(T:bool)() { return this.len != 0; } T opCast(T:int)() { return this.len; } }
Cool! Much, much nicer. (that's why I think some examples would be fine there)
Mar 08 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter Bright Wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
Thank you for the cookie too :-) I will need some more time to try all the new things. In the meantime I have already two small questions: 1) What does "Implemented attributes for constructors" in the changelog means? 2) What's the best way to translate this to the new operator regime? T foo(T)(T s) if (__traits(hasMember, T, "opAdd")) { return s + s; } I will probably write something more later, bye and thank you, bearophile
Mar 08 2010
parent bearophile <bearophileHUGS lycos.com> writes:
The Html of the change logs seems a bit wrong, the latest version now is at the
top, and in the 2.0 changelog the "Bugs Fixed" are divided in two different
horizontal alignments.
Mar 08 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 01:54:12 -0500, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Lots of meat and potatoes here, and a cookie! (spelling checker for  
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
This might belong on d.learn, but it's so specific to this release, I'll ask here: The implementation of opEquals(Object, Object) contains the following implementation (according to docs and source): bool opEquals(Object a, Object b) { if (a is b) return true; if (a is null || b is null) return false; if (typeid(a) == typeid(b)) return a.opEquals(b); return a.opEquals(b) && b.opEquals(a); } The third line seems to be a recursive call into opEquals, since the typeinfos are objects. But because the two typeid classes have the same typeinfo (TypeInfo_Class with class name "TypeInfo_Class") it will only go 2 levels deep since the first if clause will be true. However, it seems a bit redundant to verify that the typeids are not null (they will always be non-null) and have the same typeinfo (they will). Wouldn't it be more efficient and correct to just do: if(typeid(a).opEquals(typeid(b))) Also, there is a function inside object implementation to compare two typeinfos (commented out in interface file), is that used? Does the compiler allow overloading the global opEquals? Also, const is not respected: class C { int x; bool opEquals(Object other){ ++x; return false;} } void main() { const c = new C; const d = new D; assert(c != d); } compiles without complaint. I would argue that opEquals should be const in both Object and the global function, but I'm not sure of the ramifications. At the very least, the above should not compile. -Steve
Mar 08 2010
prev sibling next sibling parent reply Trass3r <un known.com> writes:
Is there a better way to use the new operator overloading than string mixins?

Also the following code strangely yields:
dsfml\system\vector2.d(47): Error: variable
dsfml.system.vector2.Vector2!(float).Vector2.op only parameters or foreach
declarations can be ref

/// element-wise operations, +, -, 
ref Vector2 opBinary(string op)(ref Vector2 v)
{
	mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op ~ "
v.y) );");
}

Removing ref from the return type makes it compile.


Furthermore the assignment operator seems to be rewritten as opBinary instead
of opAssign as the docs state:

Vector2f	_pos = Vector2f(0.f, 0.f);
yields:
Error: template instance opBinary!("=") matches more than one template
declaration


This also shows another problem. It can't distinguish between these two:
Vector2 opBinary(string op)(ref Vector2 v)
if (op != "*")
{
	mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op ~ "
v.y) );");
}

Vector2 opBinary(string op)(int i)
{
	mixin("return Vector2!(T) ( cast(T)(x " ~ op ~ " i), cast(T)(y " ~ op ~ " i)
);");
}

even though vec1 + vec2 resp. vec + 5 is unambiguous.
Mar 08 2010
parent Adam Ruppe <destructionator gmail.com> writes:
 __traits allMembers and and derivedMembers now return a tuple of strings rather
 than an array of strings. Enclose __traits in [ ] to make array literal. This
makes it
 possible for foreach statements to iterate at compile time over it.
How exciting! On 3/8/10, Trass3r <un known.com> wrote:
 Is there a better way to use the new operator overloading than string
 mixins?

 Also the following code strangely yields:
 dsfml\system\vector2.d(47): Error: variable
 dsfml.system.vector2.Vector2!(float).Vector2.op only parameters or foreach
 declarations can be ref

 /// element-wise operations, +, -,
 ref Vector2 opBinary(string op)(ref Vector2 v)
 {
 	mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op ~ "
 v.y) );");
 }

 Removing ref from the return type makes it compile.


 Furthermore the assignment operator seems to be rewritten as opBinary
 instead of opAssign as the docs state:

 Vector2f	_pos = Vector2f(0.f, 0.f);
 yields:
 Error: template instance opBinary!("=") matches more than one template
 declaration


 This also shows another problem. It can't distinguish between these two:
 Vector2 opBinary(string op)(ref Vector2 v)
 if (op != "*")
 {
 	mixin("return Vector2!(T)( cast(T)(x " ~ op ~ " v.x), cast(T)(y " ~ op ~ "
 v.y) );");
 }

 Vector2 opBinary(string op)(int i)
 {
 	mixin("return Vector2!(T) ( cast(T)(x " ~ op ~ " i), cast(T)(y " ~ op ~ "
 i) );");
 }

 even though vec1 + vec2 resp. vec + 5 is unambiguous.
Mar 08 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
A few changes that I made to Phobos and also put in the changelog don't appear in this release because I forgot to commit changelog.dd itself. $(WHATSNEW $(LI string, wstring are now bidirectional (not random) ranges) $(LI std.algorithm: defined move with one argument; levenshtein distance generalized to with all forward ranges; take now has swapped arguments) $(LI std.array: empty for arrays is now a property; front and back for a string and wstring automatically decodes the first/last character; popFront, popBack for string and wstring obey the UTF stride) $(LI std.conv: changed the default array formatting from "[a, b, c]" to "a b c") $(LI std.range: swapped order of arguments in take) $(LI std.stdio: added readln template) $(LI std.variant: now works with statically-sized arrays and const data) $(LI std.traits: added isNarrowString) ) Andrei
Mar 08 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 	$(LI std.conv: changed the default array formatting from "[a, b, c]" to 
 "a b c")
That's a regression!!! (And I think in the past it was [a,b,c] instead of [a, b, c], because it's better to save some screen space, it costs a lot!). Bye, bearophile
Mar 08 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 	$(LI std.conv: changed the default array formatting from "[a, b, c]" to 
 "a b c")
That's a regression!!! (And I think in the past it was [a,b,c] instead of [a, b, c], because it's better to save some screen space, it costs a lot!).
Sorry, this stays. The idea behind the change is to make 'to' a minimalistic function that makes minimum assumptions (e.g. the comma may be a decimal point in some languages, so is [1,2] in a German locale an array of double with one value or two? etc. The canonical "to" prints values separated by one space. Why one space? It's the most neutral thing I could think of. Why no brackets? Because of minimalism. You can very easy add them if you want them. Andrei
Mar 08 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 14:27:36 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 bearophile wrote:
 Andrei Alexandrescu:
 	$(LI std.conv: changed the default array formatting from "[a, b, c]"  
 to "a b c")
That's a regression!!! (And I think in the past it was [a,b,c] instead of [a, b, c], because it's better to save some screen space, it costs a lot!).
Sorry, this stays. The idea behind the change is to make 'to' a minimalistic function that makes minimum assumptions (e.g. the comma may be a decimal point in some languages, so is [1,2] in a German locale an array of double with one value or two? etc. The canonical "to" prints values separated by one space. Why one space? It's the most neutral thing I could think of. Why no brackets? Because of minimalism. You can very easy add them if you want them.
What about an array of strings with spaces in them? Or an array of arrays? Is there at least a way to force 'to' to format the way you want? I tend to side with bearophile on this one... -Steve
Mar 08 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 14:27:36 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 bearophile wrote:
 Andrei Alexandrescu:
     $(LI std.conv: changed the default array formatting from "[a, b, 
 c]" to "a b c")
That's a regression!!! (And I think in the past it was [a,b,c] instead of [a, b, c], because it's better to save some screen space, it costs a lot!).
Sorry, this stays. The idea behind the change is to make 'to' a minimalistic function that makes minimum assumptions (e.g. the comma may be a decimal point in some languages, so is [1,2] in a German locale an array of double with one value or two? etc. The canonical "to" prints values separated by one space. Why one space? It's the most neutral thing I could think of. Why no brackets? Because of minimalism. You can very easy add them if you want them.
What about an array of strings with spaces in them? Or an array of arrays? Is there at least a way to force 'to' to format the way you want?
Yes, you may specify the separator. Andrei
Mar 08 2010
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 14:27:36 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 bearophile wrote:
 Andrei Alexandrescu:
     $(LI std.conv: changed the default array formatting from "[a, b, 
 c]" to "a b c")
That's a regression!!! (And I think in the past it was [a,b,c] instead of [a, b, c], because it's better to save some screen space, it costs a lot!).
Sorry, this stays. The idea behind the change is to make 'to' a minimalistic function that makes minimum assumptions (e.g. the comma may be a decimal point in some languages, so is [1,2] in a German locale an array of double with one value or two? etc. The canonical "to" prints values separated by one space. Why one space? It's the most neutral thing I could think of. Why no brackets? Because of minimalism. You can very easy add them if you want them.
What about an array of strings with spaces in them? Or an array of arrays? Is there at least a way to force 'to' to format the way you want?
auto s = to!string([1,2,3], "[", ", ", "]"); -Lars
Mar 08 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
(e.g. the comma may be a decimal point in some languages, so is [1,2] in a
German locale an array of double with one value or two?<
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
It's the most neutral thing I could think of. Why no brackets? Because of
minimalism. You can very easy add them if you want them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Mar 08 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 
 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
 (e.g. the comma may be a decimal point in some languages, so is
 [1,2] in a German locale an array of double with one value or two?<
 
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
 Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
 It's the most neutral thing I could think of. Why no brackets?
 Because of minimalism. You can very easy add them if you want
 them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Your choice of leading/trailing symbols and of separators makes 'to' friendlier for printing e.g. debug strings. My choice makes it a primitive for text serialization. I'm not 100% sure which is the more frequent use and therefore which is the most appropriate as a default, but I'm leaning towards the latter. Andrei
Mar 08 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 14:49:33 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 bearophile wrote:
 Andrei Alexandrescu:

 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
 (e.g. the comma may be a decimal point in some languages, so is
 [1,2] in a German locale an array of double with one value or two?<
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
 Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
 It's the most neutral thing I could think of. Why no brackets?
 Because of minimalism. You can very easy add them if you want
 them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Your choice of leading/trailing symbols and of separators makes 'to' friendlier for printing e.g. debug strings. My choice makes it a primitive for text serialization. I'm not 100% sure which is the more frequent use and therefore which is the most appropriate as a default, but I'm leaning towards the latter.
No it doesn't. Tell me how you would parse the following text serialization string for a string[]: hello world how are you What if it was a string[][]? Compare that to: [hello world, [how are, you]] That is almost completely unambiguous (you still have to account for literal commas or brackets), whereas you have a multitude of choices with the first version. The thing is, friendlier for text-based serialization is almost identical to friendlier for printing. In fact, friendlier for text-based serialization should have even more annotations to escape delimiters. In fact, I find the defaults you defined not useful in most cases. Printing or serializing, I want to see the delimiters for the arrays, elements, and subarrays. -Steve
Mar 08 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:
 Tell me how you would parse the following text serialization string for a  
 string[]:
 
 hello world how are you
 
 What if it was a string[][]?
 
 Compare that to:
 
 [hello world, [how are, you]]
You are missing something: ["hello world", ["how are", "you"]] :-) (And yes, there are simple solutions if the strings contains " or '). Bye, bearophile
Mar 08 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 15:12:24 -0500, bearophile <bearophileHUGS lycos.com>  
wrote:

 Steven Schveighoffer:
 Tell me how you would parse the following text serialization string for  
 a
 string[]:

 hello world how are you

 What if it was a string[][]?

 Compare that to:

 [hello world, [how are, you]]
You are missing something: ["hello world", ["how are", "you"]]
For completely unambiguous, yes. But still, I find often that quotes are more noise than they are worth when just doing simple printouts. What we want is the most useful default. Also, the desired output I would like is: T[] => "[T1, T2, ..., Tn]" This would mean that strings have a special case of printing with quotes only when printed inside an array. This seems like an oddity to me. -Steve
Mar 08 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:
 For completely unambiguous, yes.  But still, I find often that quotes are  
 more noise than they are worth when just doing simple printouts.  What we  
 want is the most useful default.
Quotes add a bit of noise, but I prefer to tell apart the cases of two strings from the case of one string with a comma in the middle.
 This would mean that strings have a special case of printing with quotes  
 only when printed inside an array.  This seems like an oddity to me.
It's how Python works, that's why there are __repr__ and __str__ for objects, the repr of a string includes the quotes, its __str__ doesn't.
 a = ["hello world", ["that's right!", "you"]]
 a
['hello world', ["that's right!", 'you']]
 print a
['hello world', ["that's right!", 'you']]
 a[0]
'hello world'
 print a[0]
hello world Notes: - that 'a' contains a string and an array of strings, you usually can't do this in D, so this is not a fully representative example; - Python is dynamically typed, so it's more important that what you print shows its type. In D you can often tell it looking at type of the variable you print (unless it's hidden by a labyrinth of 'auto'). Bye, bearophile
Mar 08 2010
prev sibling parent reply Alexander Suhoverhov <alexander suhoverhov.selfip.net> writes:
Steven Schveighoffer  at "Mon, 08 Mar 2010 15:23:51 -0500" wrote:
 SS> On Mon, 08 Mar 2010 15:12:24 -0500, bearophile <bearophileHUGS lycos.com>
wrote:
 Steven Schveighoffer:
 Tell me how you would parse the following text serialization string for a
 string[]:

 hello world how are you

 What if it was a string[][]?

 Compare that to:

 [hello world, [how are, you]]
You are missing something: ["hello world", ["how are", "you"]]
SS> For completely unambiguous, yes. But still, I find often that quotes are more noise than SS> they are worth when just doing simple printouts. What we want is the most useful SS> default. Commas are even more noise than than quotes. erlang: [{app, "app1"}, {user, "user1"}, {score, 123456}, {date, 5000000}, {misc, "foo"}] But if you just drop commas: [{app "app1"} {user "user1"} {score 123456} {date 5000000} {misc "foo"}] SS> -Steve -- Best regards, Alexander Suhoverhov mailto: alexander suhoverhov.selfip.net
Mar 09 2010
next sibling parent Fawzi Mohamed <fmohamed mac.com> writes:
On 2010-03-09 09:09:51 +0100, Alexander Suhoverhov 
<alexander suhoverhov.selfip.net> said:

 
 
 Steven Schveighoffer  at "Mon, 08 Mar 2010 15:23:51 -0500" wrote:
  SS> On Mon, 08 Mar 2010 15:12:24 -0500, bearophile 
 <bearophileHUGS lycos.com> wrote:
  >> Steven Schveighoffer:
  >>> Tell me how you would parse the following text serialization string for a
  >>> string[]:
  >>>
  >>> hello world how are you
  >>>
  >>> What if it was a string[][]?
  >>>
  >>> Compare that to:
  >>>
  >>> [hello world, [how are, you]]
  >>
  >> You are missing something:
  >>
  >> ["hello world", ["how are", "you"]]
  SS> For completely unambiguous, yes.  But still, I find often that 
 quotes are more noise than
  SS> they are worth when just doing simple printouts.  What we  want is 
 the most useful
  SS> default.
 
 Commas are even more noise than than quotes. erlang:
 
 [{app, "app1"}, {user, "user1"}, {score, 123456}, {date, 5000000}, 
 {misc, "foo"}]
 
 But if you just drop commas:
 
 [{app "app1"} {user "user1"} {score 123456} {date 5000000} {misc "foo"}]
 
  SS> -Steve
For a basic output one can discuss what is better, but in general, for a serialization approach I feel that the basic approach of the discussion is flawed. A much better approach (that for example I did use in my serialization routines) is following the C++ philosophy that these details are handled by the target stream, not by the function sending the data. For example I have implemented two serializers, one that serializes to json (with [,]""), and one that serializes to a binary format. You write just one function, and then you can (even at runtime) change the details on the output, even from textual to binary, without changing anything in the serialization functions. You don't want to write a different serialization function for each format, or go around hunting for all calls to add " to strings... Now in my serialization routines I have a couple of design choices that maybe not everybody would share, but that I like: - it is possible to get a meta information describing what will be serialized *before* serializing (this helps in dumping the meta information once at the beginning, and then serialize arrays with minimal overhead in binary mode, but makes serializing slightly more complex. - it if possible (and not too difficult) to write serialization routines fully by hand, without any template, something very useful for objects that need special serialization. This method can also be fully customized. < shameless bug promotion> By the way as I have some horrible code due to http://d.puremagic.com/issues/show_bug.cgi?id=3472 and similar bugs in mixing interfaces and templates, I had written a much nicer version only to find out that it did not work... </ shameless bug promotion> I am transitioning the whole i/o in blip to a more abstract model based on simple delegates (sink/readers) that should make it easier to use it with either phobos or tango or any other source, but at the moment the input part still requires tango InputStreams (output part already transitioned). Fawzi
Mar 09 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 03:09:51 -0500, Alexander Suhoverhov  
<alexander suhoverhov.selfip.net> wrote:

 Steven Schveighoffer  at "Mon, 08 Mar 2010 15:23:51 -0500" wrote:
  SS> On Mon, 08 Mar 2010 15:12:24 -0500, bearophile  
 <bearophileHUGS lycos.com> wrote:
  >> Steven Schveighoffer:
  >>> Tell me how you would parse the following text serialization string  
 for a
  >>> string[]:
  >>>
  >>> hello world how are you
  >>>
  >>> What if it was a string[][]?
  >>>
  >>> Compare that to:
  >>>
  >>> [hello world, [how are, you]]
  >>
  >> You are missing something:
  >>
  >> ["hello world", ["how are", "you"]]
  SS> For completely unambiguous, yes.  But still, I find often that  
 quotes are more noise than
  SS> they are worth when just doing simple printouts.  What we  want is  
 the most useful
  SS> default.

 Commas are even more noise than than quotes. erlang:

 [{app, "app1"}, {user, "user1"}, {score, 123456}, {date, 5000000},  
 {misc, "foo"}]

 But if you just drop commas:

 [{app "app1"} {user "user1"} {score 123456} {date 5000000} {misc "foo"}]
If you are used to writing code, you should be used to having commas. The two major use cases for 'to!string' are debugging and maybe serialization, both programmer tasks. Plus, in your examples, you have quotes for strings. That negates the need for commas, but I don't know if having 'to' convert strings to having quotes only for arrays makes sense. Outputting an array should be a recursive thing. At the very least, we need either a non-whitespace separator or quotes to delineate strings. Brackets are a must to see the separation for multi-dimensional arrays. -Steve
Mar 09 2010
parent Fawzi Mohamed <fawzi gmx.ch> writes:
On 9-mar-10, at 13:00, Steven Schveighoffer wrote:

 On Tue, 09 Mar 2010 03:09:51 -0500, Alexander Suhoverhov
<alexander suhoverhov.selfip.net 
 wrote:
 Steven Schveighoffer  at "Mon, 08 Mar 2010 15:23:51 -0500" wrote:
 SS> On Mon, 08 Mar 2010 15:12:24 -0500, bearophile <bearophileHUGS lycos.com 
 wrote:
 Steven Schveighoffer:
 Tell me how you would parse the following text serialization  
string for a
 string[]:

 hello world how are you

 What if it was a string[][]?

 Compare that to:

 [hello world, [how are, you]]
You are missing something: ["hello world", ["how are", "you"]]
SS> For completely unambiguous, yes. But still, I find often that quotes are more noise than SS> they are worth when just doing simple printouts. What we want is the most useful SS> default. Commas are even more noise than than quotes. erlang: [{app, "app1"}, {user, "user1"}, {score, 123456}, {date, 5000000}, {misc, "foo"}] But if you just drop commas: [{app "app1"} {user "user1"} {score 123456} {date 5000000} {misc "foo"}]
If you are used to writing code, you should be used to having commas. The two major use cases for 'to!string' are debugging and maybe serialization, both programmer tasks. Plus, in your examples, you have quotes for strings. That negates the need for commas, but I don't know if having 'to' convert strings to having quotes only for arrays makes sense. Outputting an array should be a recursive thing. At the very least, we need either a non-whitespace separator or quotes to delineate strings. Brackets are a must to see the separation for multi-dimensional arrays. -Steve
I don't know, I have something similar writeOut(sink,type,formatting...), which is more flexible and efficient, not just to string. That is supposed to write out something for the user (no serialization), and well it does not put "", but it does put "," in arrays, but I can understand other choices (matlab for example has no commas). For dictionaries ":" and "," is nice I think. It really come down to the meaning of to!(x), if it should be without loss then one should have enough information to recover the original value. That is possible also without commas, but C/D programmers are used to them... lisp, or other functional languages programmers might feel more at home with spaces... both are possible. I find it slightly funny that D would choose spaces, but in the end any convention works Fawzi
Mar 09 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 14:49:33 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 bearophile wrote:
 Andrei Alexandrescu:

 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
 (e.g. the comma may be a decimal point in some languages, so is
 [1,2] in a German locale an array of double with one value or two?<
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
 Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
 It's the most neutral thing I could think of. Why no brackets?
 Because of minimalism. You can very easy add them if you want
 them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Your choice of leading/trailing symbols and of separators makes 'to' friendlier for printing e.g. debug strings. My choice makes it a primitive for text serialization. I'm not 100% sure which is the more frequent use and therefore which is the most appropriate as a default, but I'm leaning towards the latter.
No it doesn't. Tell me how you would parse the following text serialization string for a string[]: hello world how are you What if it was a string[][]? Compare that to: [hello world, [how are, you]] That is almost completely unambiguous (you still have to account for literal commas or brackets), whereas you have a multitude of choices with the first version.
I said a primitive for serialization, not a serialization infrastructure. So the basic idea is that you use "to" in conjunctions with your own routines to serialize things. "to" imposes no policy. Using "[", ", ", and "]" is policy.
 The thing is, friendlier for text-based serialization is almost 
 identical to friendlier for printing.  In fact, friendlier for 
 text-based serialization should have even more annotations to escape 
 delimiters.
 
 In fact, I find the defaults you defined not useful in most cases.  
 Printing or serializing, I want to see the delimiters for the arrays, 
 elements, and subarrays.
You can choose them no problem. std.conv gives you mechanism, you choose the policy. Andrei
Mar 08 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 15:56:14 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 14:49:33 -0500, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 bearophile wrote:
 Andrei Alexandrescu:

 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
 (e.g. the comma may be a decimal point in some languages, so is
 [1,2] in a German locale an array of double with one value or two?<
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
 Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
 It's the most neutral thing I could think of. Why no brackets?
 Because of minimalism. You can very easy add them if you want
 them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Your choice of leading/trailing symbols and of separators makes 'to' friendlier for printing e.g. debug strings. My choice makes it a primitive for text serialization. I'm not 100% sure which is the more frequent use and therefore which is the most appropriate as a default, but I'm leaning towards the latter.
No it doesn't. Tell me how you would parse the following text serialization string for a string[]: hello world how are you What if it was a string[][]? Compare that to: [hello world, [how are, you]] That is almost completely unambiguous (you still have to account for literal commas or brackets), whereas you have a multitude of choices with the first version.
I said a primitive for serialization, not a serialization infrastructure. So the basic idea is that you use "to" in conjunctions with your own routines to serialize things. "to" imposes no policy. Using "[", ", ", and "]" is policy.
Reading the documentation, it appears that setting the policy means simply passing delimiters to the "to" function. That means that for every call to "to", you specify the policy if it differs from the default. Since the default is not useful for serialization and confusing for printing, why would anyone use the default policy (aside from the obvious "because it's annoying")? If you don't use the default policy, why have a default, why not require the policy for each call?
 The thing is, friendlier for text-based serialization is almost  
 identical to friendlier for printing.  In fact, friendlier for  
 text-based serialization should have even more annotations to escape  
 delimiters.
  In fact, I find the defaults you defined not useful in most cases.   
 Printing or serializing, I want to see the delimiters for the arrays,  
 elements, and subarrays.
You can choose them no problem. std.conv gives you mechanism, you choose the policy.
I can choose the policy for each call, that is not going to look very good, and be very tedious to write. Plus it's not recursive (this would actually be a huge problem if using to for serialization): import std.stdio; import std.conv; void main() { int[][] x = new int[][](2, 2); writeln(to!string(x, "[", ",", "]")); } outputs [0 0,0 0] I would expect [[0,0],[0,0]] I'll also point out that AAs have a default policy that is much more reasonable. -Steve
Mar 08 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 15:56:14 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 14:49:33 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 bearophile wrote:
 Andrei Alexandrescu:

 Sorry, this stays.
Then I'm not going to use the Phobos printing in all my future D2 programs. As I was not using it in D1. I'm not going to change idea on this.
 (e.g. the comma may be a decimal point in some languages, so is
 [1,2] in a German locale an array of double with one value or two?<
In German you need no space after the comma, and there's no [] after and before it. So [1, 2] is not a floating point value in German.
 Why one space?<
Because that's they way people print things in natural languages. It's a convention, you know. And it's a good one. It tells apart the FP numbers and it's the minimal.
 It's the most neutral thing I could think of. Why no brackets?
 Because of minimalism. You can very easy add them if you want
 them.<
The purpose of things like the square brackets is to give a less ambiguous textual representation of the most common data structures (array and strings are the most common after numbers). So you put "" or '' around strings and [] to know what you are printing.
Your choice of leading/trailing symbols and of separators makes 'to' friendlier for printing e.g. debug strings. My choice makes it a primitive for text serialization. I'm not 100% sure which is the more frequent use and therefore which is the most appropriate as a default, but I'm leaning towards the latter.
No it doesn't. Tell me how you would parse the following text serialization string for a string[]: hello world how are you What if it was a string[][]? Compare that to: [hello world, [how are, you]] That is almost completely unambiguous (you still have to account for literal commas or brackets), whereas you have a multitude of choices with the first version.
I said a primitive for serialization, not a serialization infrastructure. So the basic idea is that you use "to" in conjunctions with your own routines to serialize things. "to" imposes no policy. Using "[", ", ", and "]" is policy.
Reading the documentation, it appears that setting the policy means simply passing delimiters to the "to" function. That means that for every call to "to", you specify the policy if it differs from the default.
I think it also means that you write your function that calls "to" inside, and use your function throughout.
 Since the default is not useful for serialization and 
 confusing for printing, why would anyone use the default policy (aside 
 from the obvious "because it's annoying")?  If you don't use the default 
 policy, why have a default, why not require the policy for each call?
Printing values with spaces between them is entirely fine for e.g. all numbers.
 The thing is, friendlier for text-based serialization is almost 
 identical to friendlier for printing.  In fact, friendlier for 
 text-based serialization should have even more annotations to escape 
 delimiters.
  In fact, I find the defaults you defined not useful in most cases.  
 Printing or serializing, I want to see the delimiters for the arrays, 
 elements, and subarrays.
You can choose them no problem. std.conv gives you mechanism, you choose the policy.
I can choose the policy for each call, that is not going to look very good, and be very tedious to write.
Write your own function and call it.
 Plus it's not recursive (this would 
 actually be a huge problem if using to for serialization):
 
 
 import std.stdio;
 import std.conv;
 void main()
 {
     int[][] x = new int[][](2, 2);
     writeln(to!string(x, "[", ",", "]"));
 }
 
 outputs [0 0,0 0]
 
 I would expect [[0,0],[0,0]]
 
 I'll also point out that AAs have a default policy that is much more 
 reasonable.
I guess that should be changed too :o). Andrei
Mar 08 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 I'll also point out that AAs have a default policy that is much more 
 reasonable.
I guess that should be changed too :o).
-.- Bye, bearophile
Mar 08 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 08 Mar 2010 17:52:25 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:


 Printing values with spaces between them is entirely fine for e.g. all  
 numbers.
You know what, you are right. Why should phobos cater to people wanting to print something as arcane as a string array, or a multi-dimensional array. People have no business using such constructs, they should be punished by having to write their own routines. It's all one-dimensional arrays of numbers for me from now on! -Steve
Mar 09 2010
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 03/09/2010 05:53 AM, Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 17:52:25 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:


 Printing values with spaces between them is entirely fine for e.g. all
 numbers.
You know what, you are right. Why should phobos cater to people wanting to print something as arcane as a string array, or a multi-dimensional array. People have no business using such constructs, they should be punished by having to write their own routines. It's all one-dimensional arrays of numbers for me from now on! -Steve
and formatted in hex
Mar 09 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ellery Newcomer wrote:
 On 03/09/2010 05:53 AM, Steven Schveighoffer wrote:
 On Mon, 08 Mar 2010 17:52:25 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:


 Printing values with spaces between them is entirely fine for e.g. all
 numbers.
You know what, you are right. Why should phobos cater to people wanting to print something as arcane as a string array, or a multi-dimensional array. People have no business using such constructs, they should be punished by having to write their own routines. It's all one-dimensional arrays of numbers for me from now on! -Steve
and formatted in hex
In wake of printing multi-dimensional arrays, I agree that start and end delimiters should be present by default. If delimiters are present, it only makes sense to make the array look like a D array, so the ", " becomes an acceptable proposition. I'm unsure about strings - should "to" go all gung-ho on quoting and escaping quotes etc.? That's a bit odd. Consider: auto str = to!string("hello world"); I'd expect the call to be an identity application that makes str equal to "hello world". So far so good. Then say I convert with "to" an array of strings to a string: auto str2 = to!string(["hello world"]); Now str2 is "\"hello world\"", i.e. has an extra pair of quotes. So "to" applied to an array does not always use "to" applied to each element of the array - it has a completely different behavior. I wonder whether that's a desirable behavior. (For the record, I agree that there are ambiguities if the quotes are not added and escaped etc. I just wonder whether that should be part of "to"s charter.) Another thing that's unclear to me is whether writeln and "to" should be defined such that write(to!string(stuff)) and writeln(stuff) produce the same text. Currently that's the general plan, but I wonder whether we should change the approach. Andrei
Mar 09 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 12:33:01 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 In wake of printing multi-dimensional arrays, I agree that start and end  
 delimiters should be present by default. If delimiters are present, it  
 only makes sense to make the array look like a D array, so the ", "  
 becomes an acceptable proposition.
That's great!
 I'm unsure about strings - should "to" go all gung-ho on quoting and  
 escaping quotes etc.? That's a bit odd. Consider:

 auto str = to!string("hello world");

 I'd expect the call to be an identity application that makes str equal  
 to "hello world". So far so good. Then say I convert with "to" an array  
 of strings to a string:

 auto str2 = to!string(["hello world"]);

 Now str2 is "\"hello world\"", i.e. has an extra pair of quotes.
I think you mean "[\"hello world\"]"
 So "to" applied to an array does not always use "to" applied to each  
 element of the array - it has a completely different behavior. I wonder  
 whether that's a desirable behavior.
I would say no. I guess you could make the argument that strings are already arrays treated specially, but I don't think it adds much to put the quotes there. Plus, it allows simpler code and documentation, you can define the conversion of an array as a purely recursive function, even if it may not be implemented that way. Note that ranges should convert identically to arrays, making arrays special would make things odd.
 Another thing that's unclear to me is whether writeln and "to" should be  
 defined such that

 write(to!string(stuff))

 and

 writeln(stuff)

 produce the same text. Currently that's the general plan, but I wonder  
 whether we should change the approach.
I like that, it shows consistency. If you want to change the format, you can via to's parameters. But the most useful defaults should be the same in writeln. Even though to is a way to get a crude serialization function, I don't know if it will be sufficient or efficient for a serious serialization library (i.e. I don't think it's worth making 'to' that smart). But it is sufficient as a debug tool, it just needs better defaults. -Steve
Mar 09 2010
parent reply Fawzi Mohamed <fawzi gmx.ch> writes:
	charset=US-ASCII;
	format=flowed;
	delsp=yes
Content-Transfer-Encoding: 7bit


On 9-mar-10, at 18:56, Steven Schveighoffer wrote:

 On Tue, 09 Mar 2010 12:33:01 -0500, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org 
 wrote:
 In wake of printing multi-dimensional arrays, I agree that start  
 and end delimiters should be present by default. If delimiters are  
 present, it only makes sense to make the array look like a D array,  
 so the ", " becomes an acceptable proposition.
That's great!
 I'm unsure about strings - should "to" go all gung-ho on quoting  
 and escaping quotes etc.? That's a bit odd. Consider:

 auto str = to!string("hello world");

 I'd expect the call to be an identity application that makes str  
 equal to "hello world". So far so good. Then say I convert with  
 "to" an array of strings to a string:

 auto str2 = to!string(["hello world"]);

 Now str2 is "\"hello world\"", i.e. has an extra pair of quotes.
I think you mean "[\"hello world\"]"
well the thing is again str vs repr (string, or representation), repr should output something that is basically valid D code that reproduces the same value, whereas str not, what should to! do?
 So "to" applied to an array does not always use "to" applied to  
 each element of the array - it has a completely different behavior.  
 I wonder whether that's a desirable behavior.
I would say no. I guess you could make the argument that strings are already arrays treated specially, but I don't think it adds much to put the quotes there. Plus, it allows simpler code and documentation, you can define the conversion of an array as a purely recursive function, even if it may not be implemented that way. Note that ranges should convert identically to arrays, making arrays special would make things odd.
 Another thing that's unclear to me is whether writeln and "to"  
 should be defined such that

 write(to!string(stuff))

 and

 writeln(stuff)

 produce the same text. Currently that's the general plan, but I  
 wonder whether we should change the approach.
then I find it much better to base everything on something like my void writeOut(T,S...)(void delegate char[]sink, T object,S formatting) that outputs to a sink, so that you can have output without memory allocation. (well my version is little more complex because I want to accept also other stuff not just a sink http://github.com/fawzi/blip/blob/master/blip/io/BasicIO.d ) If you want a single string you can easily write helpers like T[] collectAppender(T)(void delegate(void delegate(T[])) appender,char[] buf=null) or similar ( http://github.com/fawzi/blip/blob/master/blip/conta ner/GrowableArray.d ) that convert sink based stuff to a single string. I think that that design is very efficient and clean, well I have to admit that I *hate* toString and methods that convert stuff to string, because they are unnecessarily inefficent.
 I like that, it shows consistency.  If you want to change the  
 format, you can via to's parameters.  But the most useful defaults  
 should be the same in writeln.

 Even though to is a way to get a crude serialization function, I  
 don't know if it will be sufficient or efficient for a serious  
 serialization library (i.e. I don't think it's worth making 'to'  
 that smart).  But it is sufficient as a debug tool, it just needs  
 better defaults.
as I said serialization is a different beast (at least what I want from serialization), and the "how" should be in the target serializer, the serialization function should given enough information to the serializer, so that it might serialize how it pleases to him (in particular meaningful labels should be given for serialization to json,xml,...). Fawzi
Mar 09 2010
parent Fawzi Mohamed <fmohamed mac.com> writes:
On 2010-03-09 20:15:44 +0100, Fawzi Mohamed <fawzi gmx.ch> said:

[...]

 some html spam
sorry about that...
Mar 09 2010
prev sibling parent Leandro Lucarella <llucax gmail.com> writes:
Steven Schveighoffer, el  8 de marzo a las 14:57 me escribiste:
 Tell me how you would parse the following text serialization string
 for a string[]:
 
 hello world how are you
 
 What if it was a string[][]?
 
 Compare that to:
 
 [hello world, [how are, you]]
What about [1, 2]?
 That is almost completely unambiguous (you still have to account for
 literal commas or brackets), whereas you have a multitude of choices
 with the first version.
It's not too hard to be completely unambiguous. Just print the stuff in a way that is parseable for D: ["hello \"world\"", "nice \\"] [1, 2, 3] [1.0, 2.0, 3.0] Thiis is good for both serialization and debugging (it' unambiguous, mandatory for serialization, and a littl verbose but clear for debugging). And if sometime in the future we get a D parser in the stdlib, deserialization is trivial =). -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------
Mar 10 2010
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 Your choice of leading/trailing symbols and of separators makes 'to' 
 friendlier for printing e.g. debug strings. My choice makes it a 
 primitive for text serialization. I'm not 100% sure which is the more 
 frequent use and therefore which is the most appropriate as a default, 
 but I'm leaning towards the latter.
Sorry for losing my temper about this in my last posts. In Python they have faced this problem using two different things, str() and repr(), the first one produces a little more readable output, used for normal reading, and then second is a little more for textual serialization (But both use the []). The shell outputs using repr(), the print uses str(), the items inside collections are always represented with repr(). Objects can define the __repr__ and __str__. Print calls the __str__. If __str__ is missing it's used __repr__. I like handy defaults, they save time iff they are well chosen. Bye, bearophile
Mar 08 2010
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
Bug 1914 Array initialisation from const array yields memory trample was fixed, in D2 only. Can we get this into D1 as well? To show what a huge difference this bug makes, try this test case for large values of N: Executable size in bytes N D2.040 D2.041 --- ------- ------ 10 266 Kb 241 Kb 100 306 Kb 241 Kb 2000 16151 Kb 257 Kb 10K <locks up> 321 Kb --------- enum : int { N = 1000 } struct S { const float[N] BIGINIT = [7]; float a[N] = BIGINIT; } void main() {}
Mar 08 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
If you compile a program like this:

double[100_000] arr;
void main() {}

With dmd you produce a binary about 1 MB in size, because doubles in D are not
filled with zero.

So for n-D arrays bigger than a certain amount of memory, can DMD compile that
code with a zero initialization plus filling of the Nans at run-time?

Note: this produces the same very large binary, I don't know why:

double[100_000] arr = void;
static this() {
    arr[] = typeof(arr[0]).init;
}
void main() {}


While this hangs my compiler, I don't know why:

double[100_000] arr = 0.0;
static this() {
    arr[] = typeof(arr[0]).init;
}
void main() {}

Bye,
bearophile
Mar 08 2010
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 While this hangs my compiler, I don't know why:
 
 double[100_000] arr = 0.0;
 static this() {
     arr[] = typeof(arr[0]).init;
 }
 void main() {}
Well, it didn't hang, it just took a while. I found the problem.
Mar 08 2010
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 Note: this produces the same very large binary, I don't know why:
 
 double[100_000] arr = void;
 static this() {
     arr[] = typeof(arr[0]).init;
 }
 void main() {}
obj2asm tells the tale. (obj2asm is an incredibly useful tool, I don't know why nobody uses it.) double[100_000] arr = void; puts arr in the thread local storage segment. Unfortunately, there is no bss for TLS. __gshared double[100_000] arr = void; puts arr in the BSS segment, which takes up space in your executable but not the executable *file*.
Mar 08 2010
next sibling parent reply Trass3r <un known.com> writes:
 obj2asm tells the tale. (obj2asm is an incredibly useful tool, I don't 
 know why nobody uses it.)
 
Maybe because it's not free (and not much advertised). obconv also supports disassembling various object file formats + conversion between them and it's open source: http://www.agner.org/optimize/#objconv obj2asm might provide something fancy that objconv doesn't but its page doesn't show anything that would justify paying 10$.
Mar 08 2010
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Mar 08, 2010 at 04:12:00PM -0500, Trass3r wrote:
 Maybe because it's not free (and not much advertised).
The linux version comes in the zip right along side dmd. -- Adam D. Ruppe http://arsdnet.net
Mar 08 2010
parent reply Trass3r <un known.com> writes:
 The linux version comes in the zip right along side dmd.
 
Indeed. Even the OSX folder contains obj2asm. The windows version is missing.
Mar 08 2010
parent grauzone <none example.net> writes:
Trass3r wrote:
 The linux version comes in the zip right along side dmd.
Indeed. Even the OSX folder contains obj2asm. The windows version is missing.
The best thing is, on Linux you can use binutils objdump just fine. I'm sure OSX has tools to inspect object files as well. Only on Windows, you're having a bad time: almost nothing can understand digitalmars-omf.
Mar 08 2010
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Trass3r wrote:
 obj2asm tells the tale. (obj2asm is an incredibly useful tool, I
 don't know why nobody uses it.)
 
Maybe because it's not free (and not much advertised). obconv also supports disassembling various object file formats + conversion between them and it's open source: http://www.agner.org/optimize/#objconv obj2asm might provide something fancy that objconv doesn't but its page doesn't show anything that would justify paying 10$.
At first glance, obj2asm will pretty-print the codeview debug info in the object file, and will mix source lines with corresponding assembler lines. Obj2asm also comes with a bunch of other utilities, any one of which is worth the $15 if you need them: ◦chmod Change/list file attributes ◦coff2omf Convert COFF object and lib files to OMF ◦diff Compare text files ◦diffdir Compare directory trees ◦dump Dump files ◦dumpexe Dump executable files ◦dumpobj Dump object files ◦flpyimg Read/Write floppy disk image ◦grep Search files for strings ◦libunres Scan libraries for unresolved externals ◦makedep Makefile dependency generator ◦obj2asm Object file disassembler ◦patchobj Patch object files ◦smake Advanced make program ◦whereis Search for files http://www.digitalmars.com/ctg/obj2asm.html
Mar 08 2010
parent grauzone <none example.net> writes:
Walter Bright wrote:
 Trass3r wrote:
 obj2asm tells the tale. (obj2asm is an incredibly useful tool, I
 don't know why nobody uses it.)
Maybe because it's not free (and not much advertised). obconv also supports disassembling various object file formats + conversion between them and it's open source: http://www.agner.org/optimize/#objconv obj2asm might provide something fancy that objconv doesn't but its page doesn't show anything that would justify paying 10$.
At first glance, obj2asm will pretty-print the codeview debug info in the object file, and will mix source lines with corresponding assembler lines. Obj2asm also comes with a bunch of other utilities, any one of which is worth the $15 if you need them: ◦chmod Change/list file attributes ◦coff2omf Convert COFF object and lib files to OMF ◦diff Compare text files ◦diffdir Compare directory trees ◦dump Dump files ◦dumpexe Dump executable files ◦dumpobj Dump object files ◦flpyimg Read/Write floppy disk image ◦grep Search files for strings ◦libunres Scan libraries for unresolved externals ◦makedep Makefile dependency generator ◦obj2asm Object file disassembler ◦patchobj Patch object files ◦smake Advanced make program ◦whereis Search for files http://www.digitalmars.com/ctg/obj2asm.html
Why not give them out to free? Especially coff2omf seems to be critical, if you want D to be a success.
Mar 09 2010
prev sibling parent reply Bernard Helyer <b.helyer gmail.com> writes:
On 09/03/10 09:12, Walter Bright wrote:
 obj2asm tells the tale. (obj2asm is an incredibly useful tool, I don't
 know why nobody uses it.)
Maybe a minor quibble, but obj2asm is really slow. If I'm going to disassemble something, I am never going to reach for obj2asm: `ds` is a dmdscript testscript.d executable: [~]$ time objdump -d ~/bin/ds >ds.s real 0m1.139s user 0m0.912s sys 0m0.052s with '/'), obj2asm tries to interpret it as an argument. >_< real 0m55.809s user 0m11.009s sys 0m31.094s And out of curiosity, why do you charge for it on Windows, but provide it on Linux for free? Because the rest of the utilities are fairly windows-centric?
Mar 09 2010
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bernard Helyer wrote:
 On 09/03/10 09:12, Walter Bright wrote:
 obj2asm tells the tale. (obj2asm is an incredibly useful tool, I don't
 know why nobody uses it.)
Maybe a minor quibble, but obj2asm is really slow. If I'm going to disassemble something, I am never going to reach for obj2asm:
Hmm, I never noticed it being slow at all. I wonder what's going on.
 
 `ds` is a dmdscript testscript.d executable:
 
 [~]$ time objdump -d ~/bin/ds >ds.s
 
 real    0m1.139s
 user    0m0.912s
 sys    0m0.052s

 with '/'), obj2asm tries to interpret it as an argument. >_<
 
 real    0m55.809s
 user    0m11.009s
 sys    0m31.094s
 
 
 And out of curiosity, why do you charge for it on Windows, but provide 
 it on Linux for free? Because the rest of the utilities are fairly 
 windows-centric?
Yes, it's because I don't have a similar group of stuff I can bundle for Linux.
Mar 09 2010
parent reply Bernard Helyer <b.helyer gmail.com> writes:
On 10/03/10 07:54, Walter Bright wrote:

 Hmm, I never noticed it being slow at all. I wonder what's going on.
Obviously, I can't tell from here, but I can tell you what my system says obliquely. It spends that minute at 100% CPU, and about 100 megs resident (which it allocates quickly, and then hovers about at). It isn't spending a lot (almost none, AFAICT via iotop, it just does its reading and writing in a couple of big chunks) doing IO.
Mar 09 2010
parent reply Bernard Helyer <b.helyer gmail.com> writes:
On 10/03/10 08:57, Bernard Helyer wrote:
 On 10/03/10 07:54, Walter Bright wrote:

 Hmm, I never noticed it being slow at all. I wonder what's going on.
Obviously, I can't tell from here, but I can tell you what my system says obliquely. It spends that minute at 100% CPU, and about 100 megs resident (which it allocates quickly, and then hovers about at). It isn't spending a lot (almost none, AFAICT via iotop, it just does its reading and writing in a couple of big chunks) doing IO.
And of course, as you can see, it spends an atypical amount of time in kernel space. Large blocking syscall?
Mar 09 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Bernard Helyer wrote:
 On 10/03/10 08:57, Bernard Helyer wrote:
 On 10/03/10 07:54, Walter Bright wrote:

 Hmm, I never noticed it being slow at all. I wonder what's going on.
Obviously, I can't tell from here, but I can tell you what my system says obliquely. It spends that minute at 100% CPU, and about 100 megs resident (which it allocates quickly, and then hovers about at). It isn't spending a lot (almost none, AFAICT via iotop, it just does its reading and writing in a couple of big chunks) doing IO.
And of course, as you can see, it spends an atypical amount of time in kernel space. Large blocking syscall?
It's a mystery. The only I/O it does is merely read the file.
Mar 09 2010
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Don wrote:
 Bug 1914 Array initialisation from const array yields memory trample
 
 was fixed, in D2 only. Can we get this into D1 as well?
The problem is I don't think it's the right fix, and I haven't spent the time figuring it out yet.
Mar 08 2010
prev sibling next sibling parent Gareth Charnock <gareth.tpc gmail.com> writes:
I think this bug has been squished as well. Both test cases now compile 
fine.
http://d.puremagic.com/issues/show_bug.cgi?id=3694

Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for 
 error messages)
 
 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip
 
 
 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
 
 Thanks to the many people who contributed to this update!
Mar 08 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
 2) What's the best way to translate this to the new operator regime?
 
 T foo(T)(T s) if (__traits(hasMember, T, "opAdd")) {
     return s + s;
 }
I have not found a good solution yet. This solution looks buggy (also because fixed-sized arrays have a buggy .init): import std.stdio: writeln; struct Foo { int x; this(int xx) { this.x = xx; } Foo opBinary(string s:"+")(Foo other) { return Foo(this.x * other.x); } } T foo(T)(T s) if (__traits(compiles, {return T.init + T.init;})) { return s + s; // line 14 } void main() { auto f1 = Foo(2); auto f2 = Foo(3); writeln(f1 + f2); writeln(foo(f1)); int[2] a = [1, 2]; writeln(typeid(typeof(a.init))); // prints: int writeln(foo(a)); // test.d(14): Error: Array operation s + s not implemented } Bye, bearophile
Mar 08 2010
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 08/03/10 22:03, bearophile wrote:
 2) What's the best way to translate this to the new operator regime?

 T foo(T)(T s) if (__traits(hasMember, T, "opAdd")) {
      return s + s;
 }
I have not found a good solution yet. This solution looks buggy (also because fixed-sized arrays have a buggy .init):
-snip-
 T foo(T)(T s) if (__traits(compiles, {return T.init + T.init;})) {
      return s + s; // line 14
 }
Untested, will the following do what you need? ---- T foo(T)(T s) if (__traits(compiles, {return s + s;})) { return s + s; } ---- Seems like you may as well test if you can add what you're passed rather than the initial value for the type.
Mar 08 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Robert Clipsham wrote:
 On 08/03/10 22:03, bearophile wrote:
 2) What's the best way to translate this to the new operator regime?

 T foo(T)(T s) if (__traits(hasMember, T, "opAdd")) {
      return s + s;
 }
I have not found a good solution yet. This solution looks buggy (also because fixed-sized arrays have a buggy .init):
-snip-
 T foo(T)(T s) if (__traits(compiles, {return T.init + T.init;})) {
      return s + s; // line 14
 }
Untested, will the following do what you need? ---- T foo(T)(T s) if (__traits(compiles, {return s + s;})) { return s + s; } ---- Seems like you may as well test if you can add what you're passed rather than the initial value for the type.
What I usually do is: T foo(T)(T s) if (is(typeof(s + s))) { } Andrei
Mar 08 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 What I usually do is:
 T foo(T)(T s) if (is(typeof(s + s))) {
 }
Nice, thank you, I'll use that. (That solution too presents the bug 3903) Bye, bearophile
Mar 08 2010
prev sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 08/03/10 22:53, Andrei Alexandrescu wrote:
 What I usually do is:

 T foo(T)(T s) if (is(typeof(s + s))) {
 }

 Andrei
That's far nicer, I keep forgetting about is(typeof()), thanks :)
Mar 08 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Robert Clipsham wrote:
 On 08/03/10 22:53, Andrei Alexandrescu wrote:
 What I usually do is:

 T foo(T)(T s) if (is(typeof(s + s))) {
 }

 Andrei
That's far nicer, I keep forgetting about is(typeof()), thanks :)
It'll be hard to forget once TDPL will be out there, the idiom is present in several places. Man I can't wait for that book to be out. Andrei
Mar 08 2010
parent Robert Clipsham <robert octarineparrot.com> writes:
On 08/03/10 23:35, Andrei Alexandrescu wrote:
 Man I can't wait for that book to be out.
I suspect you're not the only one, I was filled with excitement when I saw the expected delivery date become earlier a few days ago, I'm eagerly awaiting it so I can start playing with D2 properly rather than just dabbling :)
Mar 08 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Robert Clipsham:
 Untested, will the following do what you need?
 ----
 T foo(T)(T s) if (__traits(compiles, {return s + s;})) {
       return s + s;
 }
 ----
 Seems like you may as well test if you can add what you're passed rather 
 than the initial value for the type.
Oh, nice, I didn't remember you can also use values there and not just types. It becomes like this then: import std.stdio: writeln; struct Foo { int x; this(int xx) { this.x = xx; } Foo opBinary(string s:"+")(Foo other) { return Foo(this.x * other.x); } } T foo(T)(T s) if (__traits(compiles, {return s + s;})) { return s + s; // line 14 } void main() { auto f1 = Foo(2); auto f2 = Foo(3); writeln(f1 + f2); writeln(foo(f1)); int[2] a = [1, 2]; writeln(typeid(typeof(a.init))); // prints: int writeln(foo(a)); // test.d(14): Error: Array operation s + s not implemented } But now I don't know what's happening, because that trait correctly returns false, but the compiler generates a compile error at line 14 still. I think there's a new bug. Bye, bearophile
Mar 08 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
 But now I don't know what's happening, because that trait correctly returns
false, but the compiler generates a compile error at line 14 still. I think
there's a new bug.
I have added a bug: http://d.puremagic.com/issues/show_bug.cgi?id=3903 Bye, bearophile
Mar 08 2010
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
    writeln(typeid(typeof(a.init))); // prints: int
?! You mean typeof(a) != typeof((typeof(a)).init) ?! Ugh... I thought (int[2]).init was [0,0] and in general (T[n]).init was [(T.init) n times]
    writeln(foo(a)); // test.d(14): Error: Array operation s + s not
 implemented
 }


 But now I don't know what's happening, because that trait correctly returns
 false, but the compiler generates a compile error at line 14 still. I think
 there's a new bug
I think your bug is this discrepancy between init's type and the original type. That needs a bug report by itself; in a template constraint, any value is at its type .init value, not its runtype value (obvious in retrospect) In your example {return s+s;} becomes {return 0+0;}, since the compiler wrongly infer (int[2]).init to be 0, a regular int. And your __traits return true: auto bar(T)(T t) { return __traits(compiles, {return t+t;});} int[2] a; writeln(bar(a)); // true! Philippe
Mar 08 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Philippe Sigaud:

    writeln(typeid(typeof(a.init))); // prints: int
?! You mean typeof(a) != typeof((typeof(a)).init) ?! Ugh... I thought (int[2]).init was [0,0] and in general (T[n]).init was [(T.init) n times]
http://d.puremagic.com/issues/show_bug.cgi?id=3826 Bye, bearophile
Mar 08 2010
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
To try the new operators I have created this helper that works:


auto operators(string[] items...) {
    struct Bunch {
        string[] items;

        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; items)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch(items);
}

struct Foo {
    int x;

    this(int xx) { this.x = xx; }

    // Foo opBinary(string s)(Foo other) if (s in ["+", "-", "*", "/"]) {
    Foo opBinary(string s)(Foo other) if (s in operators("+", "-", "*", "/")) {
        mixin("return Foo(this.x " ~ s ~ " other.x);");
    }
}



But I don't like that operators(), I'd like a more generic bunch() that works
at compile time. I have found a long series of bugs and limits trying to do
it... :-)

This works at run-time only:

auto bunch(Types...)(Types itemsTuple) {
    static struct Bunch {
        Types items;
        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; items)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch(itemsTuple);
}


This never works, I don't know why:

auto bunch(Types...)(Types itemsTuple) {
    struct Bunch {
        bool opBinaryRight(string s:"in")(string item) {
            foreach (el; itemsTuple)
                if (el == item)
                    return true;
            return false;
        }
    }

    return Bunch();
}


Maybe there is no way to have a reference to the input argument tuple in a
nonstatic nested struct, but this works:

import std.stdio: writeln;

auto equals_two(Types...)(Types items) {
    bool foo() {
        return items[0] == items[1];
    }
    return &foo;
}

void main() {
    writeln(equals_two(1, 2)());
}


Notes:

opBinaryRight("in") for arrays is useful even at compile time :-)

While doing those experiments I have seen this is not supported, because T must
be known:
auto bunch(T)(T[] items...) {

Bye,
bearophile
Mar 08 2010
prev sibling next sibling parent reply Nick Treleaven <nospam example.net> writes:
On Sun, 07 Mar 2010 22:54:12 -0800, Walter Bright wrote:

 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip
Great, thanks :) BTW on this page: http://www.digitalmars.com/d/2.0/operatoroverloading.html The 'Index Operator Overloading' link text at the top is duplicated for the link to the 'Slice Operator Overloading' section ;-)
Mar 09 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Nick Treleaven wrote:
 BTW on this page:
 http://www.digitalmars.com/d/2.0/operatoroverloading.html
 
 The 'Index Operator Overloading' link text at the top is duplicated for 
 the link to the 'Slice Operator Overloading' section ;-)
Not any more!
Mar 09 2010
prev sibling next sibling parent reply biozic <biozic free.fr> writes:
Steven Schveighoffer Wrote:

   * shrinkToFit(T[] arr): This one is a bit tricky and technically unsafe.   
 It reduces the size of the "allocated" length to fit the length of the  
 array.  The allocated length is the length that the runtime assumes is  
 being used of the memory block.  This is what aids in preventing stomping,  
 so use with care.  You can achieve stomping if you use shrinkToFit on a  
 slice, but still have references to the trimmed data.  Example:
 
 string s = "12345".idup;
 string slice = s[0..2];
 slice.shrinkToFit(); // tells the runtime that you will no longer use any data
beyond the slice
 slice ~= "00"; // appends in place, overwriting immutable data referenced  
Actually, slice.capacity *increases* from 0 to s.capacity when calling shrinkToFit, doesn't it? So "stomp" or "prepare_for_stomping" could be a better name.
Mar 09 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 10:10:10 -0500, biozic <biozic free.fr> wrote:

 Steven Schveighoffer Wrote:

   * shrinkToFit(T[] arr): This one is a bit tricky and technically  
 unsafe.
 It reduces the size of the "allocated" length to fit the length of the
 array.  The allocated length is the length that the runtime assumes is
 being used of the memory block.  This is what aids in preventing  
 stomping,
 so use with care.  You can achieve stomping if you use shrinkToFit on a
 slice, but still have references to the trimmed data.  Example:

 string s = "12345".idup;
 string slice = s[0..2];
 slice.shrinkToFit(); // tells the runtime that you will no longer use  
 any data beyond the slice
 slice ~= "00"; // appends in place, overwriting immutable data  
 referenced
Actually, slice.capacity *increases* from 0 to s.capacity when calling shrinkToFit, doesn't it? So "stomp" or "prepare_for_stomping" could be a better name.
Yes, it is technically like that. shrinkToFit really looks weird as a property of the slice you are shrinking to because it really is operating on the array data itself (which has no concrete type or reference). I don't like anything that talks about stomping, because we are not trying to say this is a stomping operation. I want to focus more on the fact that you are declaring the data after the slice as being no longer used. It's definitely a harder function to name... -Steve
Mar 09 2010
parent reply Michal Minich <michal.minich gmail.com> writes:
On Tue, 09 Mar 2010 10:23:07 -0500, Steven Schveighoffer wrote:

 I want to focus more on the fact that you are declaring the data after 
 the slice as being no longer used.
kind of assumeUnique ... assumeNoArrayReference ?
Mar 09 2010
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Michal Minich wrote:

 On Tue, 09 Mar 2010 10:23:07 -0500, Steven Schveighoffer wrote:
 
 I want to focus more on the fact that you are declaring the data after
 the slice as being no longer used.
kind of assumeUnique ... assumeNoArrayReference ?
I like that. Or assumeNoMemoryAliasing. It should be clear that it is a potentially very unsafe function.
Mar 09 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Lutger:
 Or assumeNoMemoryAliasing. It should be clear that it is a 
 potentially very unsafe function. 
This is getting there :-) Bye, bearophile
Mar 09 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 12:54:16 -0500, Lutger <lutger.blijdestijn gmail.com>  
wrote:

 Michal Minich wrote:

 On Tue, 09 Mar 2010 10:23:07 -0500, Steven Schveighoffer wrote:

 I want to focus more on the fact that you are declaring the data after
 the slice as being no longer used.
kind of assumeUnique ... assumeNoArrayReference ?
I like that. Or assumeNoMemoryAliasing. It should be clear that it is a potentially very unsafe function.
I like this train of thought, assume is a good term for what you are doing, and it is consistent with assumeUnique. The only thing I don't like about it is you aren't really assuming anything about the slice, you are assuming the data after the slice is no longer used. It looks weird that you are assuming something about the slice. assumeEndOfData ? assumeAllocation ? I don't 100% like those either. -Steve
Mar 09 2010
parent reply Michal Minich <michal.minich gmail.com> writes:
On Tue, 09 Mar 2010 14:07:10 -0500, Steven Schveighoffer wrote:

 On Tue, 09 Mar 2010 12:54:16 -0500, Lutger
 <lutger.blijdestijn gmail.com> wrote:
 
 Michal Minich wrote:

 On Tue, 09 Mar 2010 10:23:07 -0500, Steven Schveighoffer wrote:

 I want to focus more on the fact that you are declaring the data
 after the slice as being no longer used.
kind of assumeUnique ... assumeNoArrayReference ?
I like that. Or assumeNoMemoryAliasing. It should be clear that it is a potentially very unsafe function.
I like this train of thought, assume is a good term for what you are doing, and it is consistent with assumeUnique. The only thing I don't like about it is you aren't really assuming anything about the slice, you are assuming the data after the slice is no longer used. It looks weird that you are assuming something about the slice. assumeEndOfData ? assumeAllocation ? I don't 100% like those either. -Steve
assumeNoArrayReference does not express that there can be references to the original array before slice start. probably better expressing, if rather long name could be assumeNoOriginArrayReferencesPastSliceEnd assumeNoOriginArrayReferencesAfter or probably somthing like this: unsafeDeletePastSlice
Mar 09 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 14:36:41 -0500, Michal Minich  
<michal.minich gmail.com> wrote:

 assumeNoArrayReference does not express that there can be references to
 the original array before slice start. probably better expressing, if
 rather long name could be
Actually, you can have valid references up until the slice end.
 assumeNoOriginArrayReferencesPastSliceEnd
 assumeNoOriginArrayReferencesAfter
These are too long. As much as this is an unsafe to-be-used-with-care function, we don't want to torture those who need it :) I prefer a name with 1-3 terms in it.
 or probably somthing like this:
 unsafeDeletePastSlice
also a little long, and I don't like the term delete, it's not actually deleting the memory. -Steve
Mar 09 2010
parent reply David Gileadi <foo bar.com> writes:
On 3/9/2010 12:44 PM, Steven Schveighoffer wrote:
 On Tue, 09 Mar 2010 14:36:41 -0500, Michal Minich
 <michal.minich gmail.com> wrote:

 assumeNoArrayReference does not express that there can be references to
 the original array before slice start. probably better expressing, if
 rather long name could be
Actually, you can have valid references up until the slice end.
 assumeNoOriginArrayReferencesPastSliceEnd
 assumeNoOriginArrayReferencesAfter
These are too long. As much as this is an unsafe to-be-used-with-care function, we don't want to torture those who need it :) I prefer a name with 1-3 terms in it.
 or probably somthing like this:
 unsafeDeletePastSlice
also a little long, and I don't like the term delete, it's not actually deleting the memory. -Steve
As long as we're bikeshedding, maybe assumeUnreferencedAfter?
Mar 09 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 14:54:11 -0500, David Gileadi <foo bar.com> wrote:

 On 3/9/2010 12:44 PM, Steven Schveighoffer wrote:
 On Tue, 09 Mar 2010 14:36:41 -0500, Michal Minich
 <michal.minich gmail.com> wrote:

 assumeNoArrayReference does not express that there can be references to
 the original array before slice start. probably better expressing, if
 rather long name could be
Actually, you can have valid references up until the slice end.
 assumeNoOriginArrayReferencesPastSliceEnd
 assumeNoOriginArrayReferencesAfter
These are too long. As much as this is an unsafe to-be-used-with-care function, we don't want to torture those who need it :) I prefer a name with 1-3 terms in it.
 or probably somthing like this:
 unsafeDeletePastSlice
also a little long, and I don't like the term delete, it's not actually deleting the memory.
As long as we're bikeshedding, maybe assumeUnreferencedAfter?
This is exactly the semantic meaning we are going for. I'd like it to be shorter... synonyms for unreferenced? assumeUnusedAfter Any others ideas? -Steve
Mar 09 2010
parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 On Tue, 09 Mar 2010 14:54:11 -0500, David Gileadi <foo bar.com> wrote:
 
 On 3/9/2010 12:44 PM, Steven Schveighoffer wrote:
 On Tue, 09 Mar 2010 14:36:41 -0500, Michal Minich
 <michal.minich gmail.com> wrote:

 assumeNoArrayReference does not express that there can be references to
 the original array before slice start. probably better expressing, if
 rather long name could be
Actually, you can have valid references up until the slice end.
 assumeNoOriginArrayReferencesPastSliceEnd
 assumeNoOriginArrayReferencesAfter
These are too long. As much as this is an unsafe to-be-used-with-care function, we don't want to torture those who need it :) I prefer a name with 1-3 terms in it.
 or probably somthing like this:
 unsafeDeletePastSlice
also a little long, and I don't like the term delete, it's not actually deleting the memory.
As long as we're bikeshedding, maybe assumeUnreferencedAfter?
This is exactly the semantic meaning we are going for. I'd like it to be shorter... synonyms for unreferenced? assumeUnusedAfter Any others ideas? -Steve
assumeSafeExpand ?
Mar 09 2010
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 09 Mar 2010 15:29:04 -0500, Don <nospam nospam.com> wrote:

 Steven Schveighoffer wrote:
 On Tue, 09 Mar 2010 14:54:11 -0500, David Gileadi <foo bar.com> wrote:

 As long as we're bikeshedding, maybe assumeUnreferencedAfter?
This is exactly the semantic meaning we are going for. I'd like it to be shorter... synonyms for unreferenced? assumeUnusedAfter Any others ideas? -Steve
assumeSafeExpand ?
That is great! Do you think assumeSafeAppend is better, since we do call the operation append? -Steve
Mar 09 2010
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Sorry for the delayed answer.

Andrei Alexandrescu:

In wake of printing multi-dimensional arrays, I agree that start and end
delimiters should be present by default. If delimiters are present, it only
makes sense to make the array look like a D array, so the ", " becomes an
acceptable proposition.<
Good :-)
I wonder whether that's a desirable behavior.<
I like it this way (but str2 is "[\"hello world\"]", as Steven Schveighoffer says), because my programming experience has taught me that explicit is better than implicit (also as said by Python Zen), and quotation marks make the output a little more unambigous. It's a matter of balance between being fully unambigous (useful for people, but also for the computer) and being nice and readable (useful for people). It's how I have designed the put/putr functions in my dlibs, the function they both use take an extra boolean argument named "repr", that tells apart the repr/str cases. When called inside a collection then repr=true, and it's true for all successive nested recursive calls. And ["hello world"] is you write such array in normal D code, so you can perform a copy & paste from one outout into a D source code, this is a very common thing done in Python, and it's the base for the doctest module: http://docs.python.org/library/doctest.html Extra note: Python avoids many of those \ using a bit smarter quotation strategy, that involves four different symbols: " """ ' ''' While D spares the need of the """ ''' because D strings are multi line, and D uses '' to represent char literals. D1 has naked escaped char literals too but they were not appreciated much.
Currently that's the general plan, but I wonder whether we should change the
approach.<
If you or someone else shows some alternative possibilities we can discuss what is the better one. ---------------- Steven Schveighoffer:
I like that, it shows consistency.  If you want to change the format, you can
via to's parameters.  But the most useful defaults should be the same in
writeln.<
sensible defults can help a *lot* the programmers/users. ---------------- Fawzi Mohamed:
I think that that design is very efficient and clean, well I have to  
admit that I *hate* toString and methods that convert stuff to string, because they are unnecessarily inefficent.< In many cases in my code toString is used for small/medium outputs in debug mode, so performance is not so important. Computers can today generate even MB of strings in a short time. But if you want more performance, then the built-in object/struct toString may take an optional argument (that defaults to null, that means the behavour currently used), that is the sink you talk about. If you like this simple idea (that is backwards compatible if you don't add such sink arguments) you can talk about this in the main D newsgroup. Bye and thank you very much Andrei for changing your mind a little, bearophile
Mar 10 2010
prev sibling parent reply Ivan <ivan.senji gmail.com> writes:
On 8.3.2010 7:54, Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
In 2.040 this worked: real x = 1.2; real[4][4] M2 = [ [1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, 1] ]; In 2.041 it has to be written like this: real x = 1.2; real[4][4] M2 = [ [1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, cast(real)1] ]; Don't know if the first one should still work and this is a bug or is the new behaviour ok so I am checking here. The error on the first array initialization in 2.041 is Error: incompatible types for (([cast(real)1,cast(real)0,cast(real)0,x]) ? ([0,0,0,1])): 'real[]' and 'int[]' ArraysTest.d(23): Error: cannot implicitly convert expression ([0L,1L,0L,x]) of type real[] to int ArraysTest.d(23): Error: cannot implicitly convert expression ([0L,0L,1L,x]) of type real[] to int
Mar 12 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 12 Mar 2010 09:14:26 -0500, Ivan <ivan.senji gmail.com> wrote:

 On 8.3.2010 7:54, Walter Bright wrote:
 Lots of meat and potatoes here, and a cookie! (spelling checker for
 error messages)

 http://www.digitalmars.com/d/1.0/changelog.html
 http://ftp.digitalmars.com/dmd.1.057.zip


 http://www.digitalmars.com/d/2.0/changelog.html
 http://ftp.digitalmars.com/dmd.2.041.zip

 Thanks to the many people who contributed to this update!
In 2.040 this worked: real x = 1.2; real[4][4] M2 = [ [1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, 1] ]; In 2.041 it has to be written like this: real x = 1.2; real[4][4] M2 = [ [1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, cast(real)1] ]; Don't know if the first one should still work and this is a bug or is the new behaviour ok so I am checking here. The error on the first array initialization in 2.041 is Error: incompatible types for (([cast(real)1,cast(real)0,cast(real)0,x]) ? ([0,0,0,1])): 'real[]' and 'int[]' ArraysTest.d(23): Error: cannot implicitly convert expression ([0L,1L,0L,x]) of type real[] to int ArraysTest.d(23): Error: cannot implicitly convert expression ([0L,0L,1L,x]) of type real[] to int
This is a bug. Any time you are specifying the exact type on the lhs of a literal assignment, the literal should be typed that way. -Steve
Mar 12 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
 In 2.041 it has to be written like this:
 
 real x = 1.2;
 
 real[4][4] M2 = [
 	[1, 0, 0, x],
 	[0, 1, 0, x],
 	[0, 0, 1, x],
 	[0, 0, 0, cast(real)1]
 ];
I have seen something different, using dmd 2.041 on Windows. Here are few cases of code followed by the error messages dmd outputs to me. A good way to write code that contains a little less bugs is to try all possible corner cases, systematically, orthogonally, trying all the little boxes you can find in the matrix/tensor of possibilities (like Guy Steele did when he designed Java attributes). I think dmd will need few more tons of tests. ----------------------- real x = 1.2; real[4][4] M2 = [[1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, cast(real)1]]; void main() {} test.d(5): Error: non-constant expression x test.d(5): Error: non-constant expression x test.d(5): Error: non-constant expression x ----------------------- real x = 1.2; real[4][4] M2 = [[1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, 1]]; void main() {} bug1.d(5): Error: non-constant expression x bug1.d(5): Error: non-constant expression x bug1.d(5): Error: non-constant expression x ----------------------- const real x = 1.2; real[4][4] M2 = [[1, 0, 0, x], [0, 1, 0, x], [0, 0, 1, x], [0, 0, 0, 1]]; void main() {} No errors with const, immutable, enum. ----------------------- const real x = 1.2; real[4][4] M2 = [[0, 0, 1, x], [0, 0, 0, 1]]; void main() {} No errors. ----------------------- const real x = 1.2; real[4][2] M2 = [[0, 0, 1, x], [0, 0, 0, 1]]; void main() {} No errors. ----------------------- const real x = 1.2; real[2][4] M2 = [[0, 0, 1, x], [0, 0, 0, 1]]; void main() {} bug1.d(3): Error: cannot implicitly convert expression ([0,0,0,1]) of type int[] to real[2u] This seems a wrong error message at best. ----------------------- Can't x be mutable? So are array literals kinda constant now? Do you see something that needs to go to Bugzilla? Bye, bearophile
Mar 12 2010
parent bearophile <bearophileHUGS lycos.com> writes:
I have added some of those things to an older bug report:
http://d.puremagic.com/issues/show_bug.cgi?id=3948

Bye,
bearophile
Mar 13 2010