digitalmars.D - Can we drop static struct initializers?
- Don (13/13) Nov 19 2009 Now that we have struct literals, the old C-style struct initializers
- dsimcha (12/25) Nov 19 2009 I'd be inclined to say go for it, because it's yet another crufty featur...
- retard (2/30) Nov 20 2009 Well said.
- Walter Bright (7/24) Nov 19 2009 Funny, I've been thinking the same thing. Those initializers are pretty
- Justin Johansson (2/28) Nov 20 2009 Would you like another tombstone like the one I made for D. typedef?
- Don (18/44) Nov 20 2009 Dropping the whole lot would make it easier to identify delegate
- bearophile (5/5) Nov 20 2009 I've used static struct initializers because somehow the dmd optimizer i...
- Walter Bright (2/12) Nov 20 2009 The generated code should be identical. Please file a bugzilla!
- bearophile (4/5) Nov 20 2009 The last times I have shown a benchmark here, people have answered me th...
- Craig Black (6/17) Nov 20 2009 It may be frustrating trying to get others to be as performance-minded a...
- Leandro Lucarella (13/22) Nov 20 2009 Is nice to read that you like the idea of having named function
- Travis Boucher (6/20) Nov 20 2009 Whats even nicer is that dmd front end and back end are open source
- grauzone (4/26) Nov 20 2009 gdc and ldc connect the dmd frontend with free backends.
- Andrei Alexandrescu (4/30) Nov 20 2009 Would love to trim the book as well. My finger is on the Del button.
- Walter Bright (3/5) Nov 20 2009 Unless someone comes up with "I really need field names", dump 'em (but
- Andrei Alexandrescu (5/11) Nov 20 2009 My RIP emails to you (as with typedef) are my backup. Don't delete them ...
- Yigal Chripun (2/18) Nov 20 2009 what about foreach_reverse ?
- dsimcha (6/24) Nov 20 2009 IMHO this should be dropped as a keyword, but opApplyReverse should be k...
- Bill Baxter (2/3) Nov 20 2009 What about starting a different thread?
- Yigal Chripun (4/10) Nov 20 2009 Sorry.
- Bill Baxter (5/17) Nov 20 2009 No prob. Just that people interested in the topic may not see your
- Andrei Alexandrescu (6/25) Nov 20 2009 FWIW iota is written to work better with retro on floating-point numbers...
-
Walter Bright
(2/3)
Nov 20 2009
No love for foreach_reverse?
- Max Samukha (3/6) Nov 21 2009 And no mercy for opApply
- dsimcha (4/11) Nov 21 2009 opApply **must** be kept!!!! It's how my parallel foreach loop works. ...
- Max Samukha (9/20) Nov 21 2009 I guess it is possible:
- dsimcha (33/54) Nov 21 2009 I'm sorry, but I put a lot of work into getting parallel foreach working...
- Yigal Chripun (8/68) Nov 21 2009 There are three types of iteration: internal to the container, external
- dsimcha (8/76) Nov 22 2009 Exactly. I've said this before, but I think you said it much better. N...
- Andrei Alexandrescu (3/79) Nov 22 2009 Copied this message to my todo list, thanks.
- Walter Bright (3/8) Nov 21 2009 Thanks for writing this. It's nice to have a compelling argument, and
- Andrei Alexandrescu (3/16) Nov 22 2009 I think the same. Thanks, David.
- Max Samukha (14/49) Nov 23 2009 Nothing to be sorry about. I was replying to your statement that
- retard (9/35) Nov 21 2009 Sorry for asking this stupid question but why was 'iota' chosen for that...
- Leandro Lucarella (9/20) Nov 20 2009 C-style comma operator is gone, ... no, wait. I'm dreaming =P
- Bill Baxter (5/10) Nov 21 2009 Yes, but as has been point out many times, it doesn't need to occupy
- KennyTM~ (2/32) Nov 20 2009 Maybe C-style function pointer types (i.e. void(*f)(void*))? ;)
- Andrei Alexandrescu (3/18) Nov 20 2009 Would love to. At least we can deprecate them and not mention them in TD...
- Bill Baxter (14/27) Nov 20 2009 if
- Walter Bright (3/13) Nov 20 2009 I think we'd need a compelling use case for why this is needed.
- Bill Baxter (17/31) Nov 20 2009 This is the main use case I have in mind:
- Bill Baxter (14/47) Nov 20 2009 I should say that I won't really shed a tear over loss of the current
- Bill Baxter (21/34) Nov 20 2009 if
- Walter Bright (5/27) Nov 20 2009 It isn't a bug. You simply don't need constructors that progressively
- Bill Baxter (7/35) Nov 20 2009 ign
- Walter Bright (2/5) Nov 20 2009 Right, but the static initialization then shouldn't work, either.
- Bill Baxter (4/10) Nov 20 2009 Why not? It works if you use static opCall(int,int) instead of this(int...
- Walter Bright (3/12) Nov 20 2009 Because if you need runtime execution to initialize, a back door to
- Andrei Alexandrescu (3/40) Nov 20 2009 This is where CTFE should come to save the day.
- Steven Schveighoffer (16/29) Dec 29 2009 Brought up in another thread, a good use of static initializers for
- bearophile (4/6) Dec 29 2009 http://codepad.org/8HnF62s2
- Steven Schveighoffer (5/10) Dec 29 2009 OK, that makes sense. Last time I remember having issues with CTFE unle...
Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).
Nov 19 2009
== Quote from Don (nospam nospam.com)'s articleNow that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).I'd be inclined to say go for it, because it's yet another crufty feature inherited from C that I don't use, was barely aware even existed, and has been superseded by a better feature that's unique to D. What can be done with struct initializers that can't be done just as easily with struct literals? As far as I can tell (correct me if I'm wrong), nothing. IMHO we concern ourselves with C source compatibility and ease of porting C code too much sometimes. If people want a language that's source compatible with C, they want C++ and they know where to find it. If they want a language that sacrifices backwards compatibility to get rid of tons of cruft, then that's what D is and we shouldn't be ashamed of it. If we kinda sorta care about C source compatibility, we won't attract either audience.
Nov 19 2009
Fri, 20 Nov 2009 05:59:21 +0000, dsimcha wrote:== Quote from Don (nospam nospam.com)'s articleWell said.Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).I'd be inclined to say go for it, because it's yet another crufty feature inherited from C that I don't use, was barely aware even existed, and has been superseded by a better feature that's unique to D. What can be done with struct initializers that can't be done just as easily with struct literals? As far as I can tell (correct me if I'm wrong), nothing. IMHO we concern ourselves with C source compatibility and ease of porting C code too much sometimes. If people want a language that's source compatible with C, they want C++ and they know where to find it. If they want a language that sacrifices backwards compatibility to get rid of tons of cruft, then that's what D is and we shouldn't be ashamed of it. If we kinda sorta care about C source compatibility, we won't attract either audience.
Nov 20 2009
Don wrote:Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet. Or just drop the field name thing, as you suggest.
Nov 19 2009
Walter Bright wrote:Don wrote:Would you like another tombstone like the one I made for D. typedef?Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet. Or just drop the field name thing, as you suggest.
Nov 20 2009
Walter Bright wrote:Don wrote:Dropping the whole lot would make it easier to identify delegate literals. I think the code below is quite wierd. struct A { int x; } alias void delegate () B; void bar1(A a) {} void bar2(B b) {} void main() { A a = { }; B b = { }; bar1(a); // ok bar2(b); // ok bar1( {} ); // fails. And you can't even do: bar1( cast(A){} ); bar2( {} ); // ok } I suspect that there are all kinds of odd corner cases involving these guys, which haven't been explored.Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet. Or just drop the field name thing, as you suggest.
Nov 20 2009
I've used static struct initializers because somehow the dmd optimizer is able to produce more efficient code. If you replace the C-style static struct initializers in this program with D ones (the ones like Foo(1, 2)) the program gets slower: http://shootout.alioth.debian.org/debian/benchmark.php?test=nbody&lang=gdc&id=1 Maybe dmd doesn't see D-style static struct initializers as true compile-time constants, I don't know. I think LDC doesn't share this problem/limit. Bye, bearophile
Nov 20 2009
bearophile wrote:I've used static struct initializers because somehow the dmd optimizer is able to produce more efficient code. If you replace the C-style static struct initializers in this program with D ones (the ones like Foo(1, 2)) the program gets slower: http://shootout.alioth.debian.org/debian/benchmark.php?test=nbody&lang=gdc&id=1 Maybe dmd doesn't see D-style static struct initializers as true compile-time constants, I don't know. I think LDC doesn't share this problem/limit.The generated code should be identical. Please file a bugzilla!
Nov 20 2009
Walter Bright:The generated code should be identical. Please file a bugzilla!The last times I have shown a benchmark here, people have answered me that the dmd backend is primitive/old, so they have implicitly told me to not bother. So as you have noticed I have stopped showing benchmarks here for a long time, and I have focused myself in helping finding performance problems in LDC (and in LLVM itself). Recently LDC devs have slowed down their development, and they have not followed my suggestions, so I'll probably work mostly on LLVM. Bye, bearophile
Nov 20 2009
"bearophile" <bearophileHUGS lycos.com> wrote in message news:he61b9$2i9n$1 digitalmars.com...Walter Bright:It may be frustrating trying to get others to be as performance-minded as you are, but I for one appreciated very much any contributions that will make D faster. So thanks for trying, even if your advice is ignored. -CraigThe generated code should be identical. Please file a bugzilla!The last times I have shown a benchmark here, people have answered me that the dmd backend is primitive/old, so they have implicitly told me to not bother. So as you have noticed I have stopped showing benchmarks here for a long time, and I have focused myself in helping finding performance problems in LDC (and in LLVM itself). Recently LDC devs have slowed down their development, and they have not followed my suggestions, so I'll probably work mostly on LLVM. Bye, bearophile
Nov 20 2009
Walter Bright, el 19 de noviembre a las 23:53 me escribiste:Is nice to read that you like the idea of having named function parameters, even when you don't have the time or don't want to implement them :) -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Que importante, entonces en estos días de globalización refregar nuestras almas, pasarle el lampazo a nuestros corazones para alcanzar un verdadero estado de babia peperianal. -- Peperino PómoroIt's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet.
Nov 20 2009
Leandro Lucarella wrote:Walter Bright, el 19 de noviembre a las 23:53 me escribiste:Whats even nicer is that dmd front end and back end are open source allowing anyone to implement them if they really want to. Of course it will be even nicerer once the back end is at a state where it can be under a less restrictive license (single user, no redistribution? seriously?).Is nice to read that you like the idea of having named function parameters, even when you don't have the time or don't want to implement them :)It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet.
Nov 20 2009
Travis Boucher wrote:Leandro Lucarella wrote:gdc and ldc connect the dmd frontend with free backends. Of course, it gets harder to send Walter a patch in this case, and I would expect that such a patch is simply ignored.Walter Bright, el 19 de noviembre a las 23:53 me escribiste:Whats even nicer is that dmd front end and back end are open source allowing anyone to implement them if they really want to. Of course it will be even nicerer once the back end is at a state where it can be under a less restrictive license (single user, no redistribution? seriously?).Is nice to read that you like the idea of having named function parameters, even when you don't have the time or don't want to implement them :)It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet.
Nov 20 2009
Walter Bright wrote:Don wrote:Would love to trim the book as well. My finger is on the Del button. Just say a word. AndreiNow that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet. Or just drop the field name thing, as you suggest.
Nov 20 2009
Andrei Alexandrescu wrote:Would love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
Walter Bright wrote:Andrei Alexandrescu wrote:My RIP emails to you (as with typedef) are my backup. Don't delete them :o). So, C-style arrays are gone, C-style struct initializers are gone, typedef is gone. __traits isn't feeling too well either :o). AndreiWould love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
Andrei Alexandrescu wrote:Walter Bright wrote:what about foreach_reverse ?Andrei Alexandrescu wrote:My RIP emails to you (as with typedef) are my backup. Don't delete them :o). So, C-style arrays are gone, C-style struct initializers are gone, typedef is gone. __traits isn't feeling too well either :o). AndreiWould love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
== Quote from Yigal Chripun (yigal100 gmail.com)'s articleAndrei Alexandrescu wrote:IMHO this should be dropped as a keyword, but opApplyReverse should be kept. Calling std.range.retro() with a type where iteration works via opApply, not ranges, should cause Retro.opApply to forward to opApplyReverse. This would preserve consistency between iterating over ranges and opApply types and get rid of a really ugly keyword.Walter Bright wrote:what about foreach_reverse ?Andrei Alexandrescu wrote:My RIP emails to you (as with typedef) are my backup. Don't delete them :o). So, C-style arrays are gone, C-style struct initializers are gone, typedef is gone. __traits isn't feeling too well either :o). AndreiWould love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
On Fri, Nov 20, 2009 at 11:15 AM, Yigal Chripun <yigal100 gmail.com> wrote:what about foreach_reverse ?What about starting a different thread?
Nov 20 2009
Bill Baxter wrote:On Fri, Nov 20, 2009 at 11:15 AM, Yigal Chripun <yigal100 gmail.com> wrote:Sorry. I assumed we were discussing removals from D and therefore mentioned foreach_reverse as a prime candidate. I'll start a new thread.what about foreach_reverse ?What about starting a different thread?
Nov 20 2009
On Fri, Nov 20, 2009 at 11:55 AM, Yigal Chripun <yigal100 gmail.com> wrote:Bill Baxter wrote:No prob. Just that people interested in the topic may not see your message if it's buried under the heading of "static struct initializers". --bbOn Fri, Nov 20, 2009 at 11:15 AM, Yigal Chripun <yigal100 gmail.com> wrote:Sorry. I assumed we were discussing removals from D and therefore mentioned foreach_reverse as a prime candidate. I'll start a new thread.what about foreach_reverse ?What about starting a different thread?
Nov 20 2009
Yigal Chripun wrote:Andrei Alexandrescu wrote:FWIW iota is written to work better with retro on floating-point numbers than foreach_reverse. However, it does one addition and one multiplication per iteration; foreach_revers only does one addition. The multiplication, however, gives iota precise semantics. AndreiWalter Bright wrote:what about foreach_reverse ?Andrei Alexandrescu wrote:My RIP emails to you (as with typedef) are my backup. Don't delete them :o). So, C-style arrays are gone, C-style struct initializers are gone, typedef is gone. __traits isn't feeling too well either :o). AndreiWould love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
Yigal Chripun wrote:what about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 20 2009
On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
== Quote from Max Samukha (spambox d-coding.com)'s articleOn Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
On Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
== Quote from Max Samukha (spambox d-coding.com)'s articleOn Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:I'm sorry, but I put a lot of work into getting parallel foreach working, and I also have a few other pieces of code that depend on opApply and could not (easily) be rewritten in terms of ranges. I feel very strongly that opApply and ranges accomplish different enough goals that they should both be kept. opApply is good when you **just** want to define foreach syntax and nothing else, with maximum flexibility as to how the foreach syntax is implemented. Ranges are good when you want to solve a superset of this problem and define iteration over your object more generally, giving up some flexibility as to how this iteration will be implemented. Furthermore, ranges don't allow for overloading based on the iteration type. For example, you can't do this with ranges: foreach(char[] line; file) {} // Recycles buffer. foreach(string line; file) {} // Doesn't recycle buffer. They also don't allow iterating over more than one variable, like: foreach(var1, var2, var3; myObject) {} Contrary to popular belief, opApply doesn't even have to be slow. Ranges can be as slow as or slower than opApply if at least one of the three functions (front, popFront, empty) is not inlined. This actually happens in practice. For example, based on reading disassemblies and the code to inline.c, neither front() nor popFront() in std.range.Take is ever inlined. If the range functions are virtual, none of them will be inlined. Just as importantly, I've confirmed by reading the disassembly that LDC is capable of inlining the loop body of opApply at optimization levels >= O3. If D becomes mainstream, D2 will eventually also be implemented on a compiler that's smart enough to do stuff like this. To remove opApply for performance reasons would be to let the capabilities of DMD's current optimizer influence long-term design decisions. If anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
dsimcha wrote:== Quote from Max Samukha (spambox d-coding.com)'s articleThere are three types of iteration: internal to the container, external by index, pointer, range, etc, and a third design with co-routines (fibers) in which the container internally iterates itself and yields a single item on each call. Ranges accomplish only the external type of iteration. opApply allows for internal iteration. All three strategies have their uses and should be allowed in D.On Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:I'm sorry, but I put a lot of work into getting parallel foreach working, and I also have a few other pieces of code that depend on opApply and could not (easily) be rewritten in terms of ranges. I feel very strongly that opApply and ranges accomplish different enough goals that they should both be kept. opApply is good when you **just** want to define foreach syntax and nothing else, with maximum flexibility as to how the foreach syntax is implemented. Ranges are good when you want to solve a superset of this problem and define iteration over your object more generally, giving up some flexibility as to how this iteration will be implemented. Furthermore, ranges don't allow for overloading based on the iteration type. For example, you can't do this with ranges: foreach(char[] line; file) {} // Recycles buffer. foreach(string line; file) {} // Doesn't recycle buffer. They also don't allow iterating over more than one variable, like: foreach(var1, var2, var3; myObject) {} Contrary to popular belief, opApply doesn't even have to be slow. Ranges can be as slow as or slower than opApply if at least one of the three functions (front, popFront, empty) is not inlined. This actually happens in practice. For example, based on reading disassemblies and the code to inline.c, neither front() nor popFront() in std.range.Take is ever inlined. If the range functions are virtual, none of them will be inlined. Just as importantly, I've confirmed by reading the disassembly that LDC is capable of inlining the loop body of opApply at optimization levels >= O3. If D becomes mainstream, D2 will eventually also be implemented on a compiler that's smart enough to do stuff like this. To remove opApply for performance reasons would be to let the capabilities of DMD's current optimizer influence long-term design decisions. If anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
== Quote from Yigal Chripun (yigal100 gmail.com)'s articledsimcha wrote:would== Quote from Max Samukha (spambox d-coding.com)'s articleOn Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:== Quote from Max Samukha (spambox d-coding.com)'s articleOn Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. ThisYigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>Exactly. I've said this before, but I think you said it much better. Now that Walter has agreed to keep opApply, this should really be explained somewhere in TDPL and in the online docs to clarify to newcomers why someone would choose opApply over ranges or vice-versa. External iteration is more flexible for the user of the object, internal iteration is more flexible for the designer of the object.There are three types of iteration: internal to the container, external by index, pointer, range, etc, and a third design with co-routines (fibers) in which the container internally iterates itself and yields a single item on each call. Ranges accomplish only the external type of iteration. opApply allows for internal iteration. All three strategies have their uses and should be allowed in D.I'm sorry, but I put a lot of work into getting parallel foreach working, and I also have a few other pieces of code that depend on opApply and could not (easily) be rewritten in terms of ranges. I feel very strongly that opApply and ranges accomplish different enough goals that they should both be kept. opApply is good when you **just** want to define foreach syntax and nothing else, with maximum flexibility as to how the foreach syntax is implemented. Ranges are good when you want to solve a superset of this problem and define iteration over your object more generally, giving up some flexibility as to how this iteration will be implemented. Furthermore, ranges don't allow for overloading based on the iteration type. For example, you can't do this with ranges: foreach(char[] line; file) {} // Recycles buffer. foreach(string line; file) {} // Doesn't recycle buffer. They also don't allow iterating over more than one variable, like: foreach(var1, var2, var3; myObject) {} Contrary to popular belief, opApply doesn't even have to be slow. Ranges can be as slow as or slower than opApply if at least one of the three functions (front, popFront, empty) is not inlined. This actually happens in practice. For example, based on reading disassemblies and the code to inline.c, neither front() nor popFront() in std.range.Take is ever inlined. If the range functions are virtual, none of them will be inlined. Just as importantly, I've confirmed by reading the disassembly that LDC is capable of inlining the loop body of opApply at optimization levels >= O3. If D becomes mainstream, D2 will eventually also be implemented on a compiler that's smart enough to do stuff like this. To remove opApply for performance reasons would be to let the capabilities of DMD's current optimizer influence long-term design decisions. If anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.I guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?
Nov 22 2009
dsimcha wrote:== Quote from Yigal Chripun (yigal100 gmail.com)'s articleCopied this message to my todo list, thanks. Andreidsimcha wrote:would== Quote from Max Samukha (spambox d-coding.com)'s articleOn Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:== Quote from Max Samukha (spambox d-coding.com)'s articleOn Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. ThisYigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>Exactly. I've said this before, but I think you said it much better. Now that Walter has agreed to keep opApply, this should really be explained somewhere in TDPL and in the online docs to clarify to newcomers why someone would choose opApply over ranges or vice-versa. External iteration is more flexible for the user of the object, internal iteration is more flexible for the designer of the object.There are three types of iteration: internal to the container, external by index, pointer, range, etc, and a third design with co-routines (fibers) in which the container internally iterates itself and yields a single item on each call. Ranges accomplish only the external type of iteration. opApply allows for internal iteration. All three strategies have their uses and should be allowed in D.I'm sorry, but I put a lot of work into getting parallel foreach working, and I also have a few other pieces of code that depend on opApply and could not (easily) be rewritten in terms of ranges. I feel very strongly that opApply and ranges accomplish different enough goals that they should both be kept. opApply is good when you **just** want to define foreach syntax and nothing else, with maximum flexibility as to how the foreach syntax is implemented. Ranges are good when you want to solve a superset of this problem and define iteration over your object more generally, giving up some flexibility as to how this iteration will be implemented. Furthermore, ranges don't allow for overloading based on the iteration type. For example, you can't do this with ranges: foreach(char[] line; file) {} // Recycles buffer. foreach(string line; file) {} // Doesn't recycle buffer. They also don't allow iterating over more than one variable, like: foreach(var1, var2, var3; myObject) {} Contrary to popular belief, opApply doesn't even have to be slow. Ranges can be as slow as or slower than opApply if at least one of the three functions (front, popFront, empty) is not inlined. This actually happens in practice. For example, based on reading disassemblies and the code to inline.c, neither front() nor popFront() in std.range.Take is ever inlined. If the range functions are virtual, none of them will be inlined. Just as importantly, I've confirmed by reading the disassembly that LDC is capable of inlining the loop body of opApply at optimization levels >= O3. If D becomes mainstream, D2 will eventually also be implemented on a compiler that's smart enough to do stuff like this. To remove opApply for performance reasons would be to let the capabilities of DMD's current optimizer influence long-term design decisions. If anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.I guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?
Nov 22 2009
dsimcha wrote:If anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.Thanks for writing this. It's nice to have a compelling argument, and you gave one. Looks like opApply is staying.
Nov 21 2009
Walter Bright wrote:dsimcha wrote:I think the same. Thanks, David. AndreiIf anyone sees any harm in keeping opApply other than a slightly larger language spec, please let me know. Despite its having been superseded by ranges for a subset of use cases (and this subset, I will acknowledge, is better handled by ranges), I actually think the flexibility it gives in terms of how foreach can be implemented makes it one of D's best features.Thanks for writing this. It's nice to have a compelling argument, and you gave one. Looks like opApply is staying.
Nov 22 2009
On Sat, 21 Nov 2009 20:21:54 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:Nothing to be sorry about. I was replying to your statement that parallel foreach cannot be implemented in terms of ranges.I guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?I'm sorry, but I put a lot of work into getting parallel foreach working, and I also have a few other pieces of code that depend on opApply and could not (easily) be rewritten in terms of ranges. I feel very strongly that opApply and ranges accomplish different enough goals that they should both be kept.opApply is good when you **just** want to define foreach syntax and nothing else, with maximum flexibility as to how the foreach syntax is implemented. Ranges are good when you want to solve a superset of this problem and define iteration over your object more generally, giving up some flexibility as to how this iteration will be implemented. Furthermore, ranges don't allow for overloading based on the iteration type. For example, you can't do this with ranges: foreach(char[] line; file) {} // Recycles buffer. foreach(string line; file) {} // Doesn't recycle buffer.OkThey also don't allow iterating over more than one variable, like: foreach(var1, var2, var3; myObject) {}I guess it is a relatively rare case. And you can always provide a range returning a tuple. foreach(r; myObject.range) { writeln(r.front.var1, r.front.var2, r.front.var3); } The common case of iterating over index and value of a random access range should be supported by foreach.Contrary to popular belief, opApply doesn't even have to be slow. Ranges can be as slow as or slower than opApply if at least one of the three functions (front, popFront, empty) is not inlined. This actually happens in practice. For example, based on reading disassemblies and the code to inline.c, neither front() nor popFront() in std.range.Take is ever inlined.I think that is a problem with the compiler, not ranges.If the range functions are virtual, none of them will be inlined.OkJust as importantly, I've confirmed by reading the disassembly that LDC is capable of inlining the loop body of opApply at optimization levels >= O3. If D becomes mainstream, D2 will eventually also be implemented on a compiler that's smart enough to do stuff like this. To remove opApply for performance reasons would be to let the capabilities of DMD's current optimizer influence long-term design decisions.Convinced. Let's keep opApply.
Nov 23 2009
Sat, 21 Nov 2009 21:49:21 +0200, Max Samukha wrote:On Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:Sorry for asking this stupid question but why was 'iota' chosen for that purpose? I was kind of expecting that D2 would have these extension methods which would allow writing '0.to(numbers.length)' by defining 'auto to(int begin, int end) { ... }'. I looked at wikipedia (http:// en.wikipedia.org/wiki/Iota) and they seem to give credit for the Go programming language which seems rather weird since they probably existed in D long before Go was released. I've never heard of this APL being used anywhere.== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
== Quote from retard (re tard.com.invalid)'s articleSat, 21 Nov 2009 21:49:21 +0200, Max Samukha wrote:Because parallel foreach works over arbitrary ranges (though somewhat inefficiently over non-random access ranges) and iota is what's implemented now, so that's what I used in my examples. If we get extension methos and 0.to(numbers.length) returns a random access range of integers [0, numbers.length) , then this will work, too.On Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha <dsimcha yahoo.com> wrote:Sorry for asking this stupid question but why was 'iota' chosen for that purpose? I was kind of expecting that D2 would have these extension methods which would allow writing '0.to(numbers.length)' by defining 'auto to(int begin, int end) { ... }'. I looked at wikipedia (http:// en.wikipedia.org/wiki/Iota) and they seem to give credit for the Go programming language which seems rather weird since they probably existed in D long before Go was released. I've never heard of this APL being used anywhere.== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse? <tear>
Nov 21 2009
On Nov 22, 09 04:32, retard wrote:Sat, 21 Nov 2009 21:49:21 +0200, Max Samukha wrote:Because C++ used iota. Although "range" is easier to understand, and I would say an C++ programmer has higher chance to know what is range(1,10) than iota(1,10). Also, "to" has been used in conversion (e.g. to!(string)(345))On Sat, 21 Nov 2009 18:51:40 +0000 (UTC), dsimcha<dsimcha yahoo.com> wrote:Sorry for asking this stupid question but why was 'iota' chosen for that purpose? I was kind of expecting that D2 would have these extension methods which would allow writing '0.to(numbers.length)' by defining 'auto to(int begin, int end) { ... }'. I looked at wikipedia (http:// en.wikipedia.org/wiki/Iota) and they seem to give credit for the Go programming language which seems rather weird since they probably existed in D long before Go was released. I've never heard of this APL being used anywhere.== Quote from Max Samukha (spambox d-coding.com)'s articleI guess it is possible: uint[] numbers = new uint[1_000]; pool.parallel_each!((size_t i){ numbers[i] = i; })(iota(0, numbers.length)); Though I agree it's not as cute but it is faster since the delegate is called directly. Or did I miss something?On Fri, 20 Nov 2009 15:30:48 -0800, Walter Bright <newshound1 digitalmars.com> wrote:opApply **must** be kept!!!! It's how my parallel foreach loop works. This would be **impossible** to implement with ranges. If opApply is removed now, I will fork the language over it.Yigal Chripun wrote:And no mercy for opApplywhat about foreach_reverse ?No love for foreach_reverse?<tear>
Nov 21 2009
Andrei Alexandrescu, el 20 de noviembre a las 10:42 me escribiste:Walter Bright wrote:C-style comma operator is gone, ... no, wait. I'm dreaming =P -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- No existiría el sonido del mar si faltara en la vida oreja y caracol. -- Ricardo Vaporeso. Cosquín, 1908.Andrei Alexandrescu wrote:My RIP emails to you (as with typedef) are my backup. Don't delete them :o). So, C-style arrays are gone, C-style struct initializers are gone,Would love to trim the book as well. My finger is on the Del button. Just say a word.Unless someone comes up with "I really need field names", dump 'em (but save a backup of your work first!).
Nov 20 2009
On Sat, Nov 21, 2009 at 3:07 AM, retard <re tard.com.invalid> wrote:Fri, 20 Nov 2009 17:06:44 -0300, Leandro Lucarella wrote:Yes, but as has been point out many times, it doesn't need to occupy such a plumb piece of syntactical real estate in order to be a useful code gen construct. --bbIt will never die. It's a perfect construct to be used in code generation.So, C-style arrays are gone, C-style struct initializers are gone,C-style comma operator is gone, ... no, wait. I'm dreaming =P
Nov 21 2009
On Nov 21, 09 00:15, Andrei Alexandrescu wrote:Walter Bright wrote:Maybe C-style function pointer types (i.e. void(*f)(void*))? ;)Don wrote:Would love to trim the book as well. My finger is on the Del button. Just say a word. AndreiNow that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Funny, I've been thinking the same thing. Those initializers are pretty much obsolete, the only thing left is the field name thing. To keep the field name thing with the newer struct literals would require named function parameters as well, something doable but I'm not ready to do all the work to implement that yet. Or just drop the field name thing, as you suggest.
Nov 20 2009
Don wrote:Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Would love to. At least we can deprecate them and not mention them in TDPL. Andrei
Nov 20 2009
On Thu, Nov 19, 2009 at 9:48 PM, Don <nospam nospam.com> wrote:Now that we have struct literals, the old C-style struct initializers don='tseem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ =A0 int D; } enum Move genMove =3D { D:4 }; immutable Move b =3D genMove; It's not difficult to fix these compiler problems, but I'm just not sure =ifit's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).I agree there are too many ways to make structs, but... 1) Struct literals don't work if you have an opCall for your struct. (Maybe that's not such a big deal now that structs have constructors? I haven't had a chance to look into struct constructors yet...) 2) The field:value style struct initializer is probably the closest D will ever get to named arguments. I think perhaps it should require the struct name, and be treated as a struct literal rather than static initializer: auto anS =3D S{D:4}; <=3D> auto anS =3D S(4) --bb
Nov 20 2009
Bill Baxter wrote:1) Struct literals don't work if you have an opCall for your struct. (Maybe that's not such a big deal now that structs have constructors? I haven't had a chance to look into struct constructors yet...)Worst case, you can still construct them dynamically.2) The field:value style struct initializer is probably the closest D will ever get to named arguments. I think perhaps it should require the struct name, and be treated as a struct literal rather than static initializer: auto anS = S{D:4}; <=> auto anS = S(4)I think we'd need a compelling use case for why this is needed.
Nov 20 2009
On Fri, Nov 20, 2009 at 10:29 AM, Walter Bright <newshound1 digitalmars.com> wrote:Bill Baxter wrote:This is the main use case I have in mind: void runAlgo(Options opt); struct Options { bool useFrobbing =3D false; int numIters =3D 200; float tolerance =3D 1e-4; int verbosity =3D 0; // ... } runAlgo( Options{verbosity:100} ); instead of Options opt; opt.verbosity =3D 100; runAlgo(opt); --bb1) Struct literals don't work if you have an opCall for your struct. =A0 =A0(Maybe that's not such a big deal now that structs have constructors? =A0I haven't had a chance to look into struct constructors yet...)Worst case, you can still construct them dynamically.2) The field:value style struct initializer is probably the closest D will ever get to named arguments. =A0I think perhaps it should require the struct name, and be treated as a struct literal rather than static initializer: =A0 =A0 =A0auto anS =3D S{D:4}; =A0 <=3D> =A0 auto anS =3D S(4)I think we'd need a compelling use case for why this is needed.
Nov 20 2009
On Fri, Nov 20, 2009 at 10:58 AM, Bill Baxter <wbaxter gmail.com> wrote:On Fri, Nov 20, 2009 at 10:29 AM, Walter Bright <newshound1 digitalmars.com> wrote:sBill Baxter wrote:1) Struct literals don't work if you have an opCall for your struct. =A0 =A0(Maybe that's not such a big deal now that structs have constructors? =A0I haven't had a chance to look into struct constructor=I should say that I won't really shed a tear over loss of the current static-only {a:b} syntax. But I would like to see something similar resurrected as a fully dynamic construct for the use case of large numbers of options with good defaults for most. I see no reason the compiler shouldn't be able to turn runAlgo( Options{verbosity:100} ); into Options _tmp; _tmp.verbosity =3D 100; runAlgo( _tmp ); --bbThis is the main use case I have in mind: void runAlgo(Options opt); struct Options { =A0 =A0bool useFrobbing =3D false; =A0 =A0int numIters =3D 200; =A0 =A0float tolerance =3D 1e-4; =A0 =A0int verbosity =3D 0; =A0 =A0// ... =A0} runAlgo( Options{verbosity:100} ); instead of Options opt; opt.verbosity =3D 100; runAlgo(opt);yet...)Worst case, you can still construct them dynamically.2) The field:value style struct initializer is probably the closest D will ever get to named arguments. =A0I think perhaps it should require the struct name, and be treated as a struct literal rather than static initializer: =A0 =A0 =A0auto anS =3D S{D:4}; =A0 <=3D> =A0 auto anS =3D S(4)I think we'd need a compelling use case for why this is needed.
Nov 20 2009
On Thu, Nov 19, 2009 at 9:48 PM, Don <nospam nospam.com> wrote:Now that we have struct literals, the old C-style struct initializers don='tseem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ =A0 int D; } enum Move genMove =3D { D:4 }; immutable Move b =3D genMove; It's not difficult to fix these compiler problems, but I'm just not sure =ifit's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Here's one thing I just found: struct constructors don't work at compile-time: struct Struct { this(int _n, float _x) { n =3D _n; x =3D _x; } int n; float x; } enum A =3D Struct(1,2); // Error: cannot evaluate ((Struct __ctmp1; // ) , __ctmp1).this(1,2F) at compile time The C-style initializer works. static opCall works too. But if that bug is fixed, then I can't think of a reason to have the classic C-style no-colons syntax. --bb
Nov 20 2009
Bill Baxter wrote:Here's one thing I just found: struct constructors don't work at compile-time: struct Struct { this(int _n, float _x) { n = _n; x = _x; } int n; float x; } enum A = Struct(1,2); // Error: cannot evaluate ((Struct __ctmp1; // ) , __ctmp1).this(1,2F) at compile time The C-style initializer works. static opCall works too. But if that bug is fixed, then I can't think of a reason to have the classic C-style no-colons syntax.It isn't a bug. You simply don't need constructors that progressively assign parameters to fields. Struct(1,2); works just fine without that constructor being defined.
Nov 20 2009
On Fri, Nov 20, 2009 at 3:34 PM, Walter Bright <newshound1 digitalmars.com> wrote:Bill Baxter wrote:ignHere's one thing I just found: struct constructors don't work at compile-time: struct Struct { =A0 =A0this(int _n, float _x) { =A0 =A0 =A0 =A0n =3D _n; x =3D _x; =A0 =A0} =A0 =A0int n; =A0 =A0float x; } enum A =3D Struct(1,2); // Error: cannot evaluate ((Struct __ctmp1; // ) , __ctmp1).this(1,2F) at compile time The C-style initializer works. static opCall works too. But if that bug is fixed, then I can't think of a reason to have the classic C-style no-colons syntax.It isn't a bug. You simply don't need constructors that progressively ass=parameters to fields. =A0 Struct(1,2); works just fine without that constructor being defined.Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time. --bb
Nov 20 2009
Bill Baxter wrote:Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 20 2009
On Fri, Nov 20, 2009 at 4:05 PM, Walter Bright <newshound1 digitalmars.com> wrote:Bill Baxter wrote:Why not? It works if you use static opCall(int,int) instead of this(int,int). --bbRight, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 20 2009
Bill Baxter wrote:On Fri, Nov 20, 2009 at 4:05 PM, Walter Bright <newshound1 digitalmars.com> wrote:Because if you need runtime execution to initialize, a back door to statically initialize it looks like a bug.Bill Baxter wrote:Why not? It works if you use static opCall(int,int) instead of this(int,int).Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 20 2009
Walter Bright wrote:Bill Baxter wrote:No, it's a known bug. The problem is that a constructor call A a(b); gets changed into (A __a;, __a.opThis()) The scope of __a is whereever it's called from. In the case of const int X = foo(A a); __ is in global scope, so it's a static variable, and therefore can't be used in CTFE! But of course it's not a genuine static, it's just an artifact of the transformation. Exactly the same problem happens with variadic arguments. And for pretty much the same reason, you get an ICE if you declare a struct with a constructor as a default function parameter. I'm not sure, but it could be that int parameters also become shared variables? One way to fix it might be to introduce a flag such that compiler-generated statics are marked so that they can distinguished from real statics.On Fri, Nov 20, 2009 at 4:05 PM, Walter Bright <newshound1 digitalmars.com> wrote:Because if you need runtime execution to initialize, a back door to statically initialize it looks like a bug.Bill Baxter wrote:Why not? It works if you use static opCall(int,int) instead of this(int,int).Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 20 2009
Hello Walter,Bill Baxter wrote:who said anything about needing runtime? If the constructor can be evaluated as CTFE with it's only result being the struct getting set up, why not let it. I can think of serval useful thing to do with that (validation, denormalization, etc.)On Fri, Nov 20, 2009 at 4:05 PM, Walter Bright <newshound1 digitalmars.com> wrote:Because if you need runtime execution to initialize, a back door to statically initialize it looks like a bug.Bill Baxter wrote:Why not? It works if you use static opCall(int,int) instead of this(int,int).Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 23 2009
BCS wrote:Hello Walter,Read my post. It's just a compiler bug.Bill Baxter wrote:who said anything about needing runtime? If the constructor can be evaluated as CTFE with it's only result being the struct getting set up, why not let it. I can think of serval useful thing to do with that (validation, denormalization, etc.)On Fri, Nov 20, 2009 at 4:05 PM, Walter Bright <newshound1 digitalmars.com> wrote:Because if you need runtime execution to initialize, a back door to statically initialize it looks like a bug.Bill Baxter wrote:Why not? It works if you use static opCall(int,int) instead of this(int,int).Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time.Right, but the static initialization then shouldn't work, either.
Nov 23 2009
Bill Baxter wrote:On Fri, Nov 20, 2009 at 3:34 PM, Walter Bright <newshound1 digitalmars.com> wrote:This is where CTFE should come to save the day. AndreiBill Baxter wrote:Right, but if you do define it (in order to do something extra upon initialization -- validate inputs or what have you) then it no longer works at compile time. --bbHere's one thing I just found: struct constructors don't work at compile-time: struct Struct { this(int _n, float _x) { n = _n; x = _x; } int n; float x; } enum A = Struct(1,2); // Error: cannot evaluate ((Struct __ctmp1; // ) , __ctmp1).this(1,2F) at compile time The C-style initializer works. static opCall works too. But if that bug is fixed, then I can't think of a reason to have the classic C-style no-colons syntax.It isn't a bug. You simply don't need constructors that progressively assign parameters to fields. Struct(1,2); works just fine without that constructor being defined.
Nov 20 2009
On Fri, 20 Nov 2009 00:48:28 -0500, Don <nospam nospam.com> wrote:Now that we have struct literals, the old C-style struct initializers don't seem to be necessary. The variations with named initializers are not really implemented -- the example in the spec doesn't work, and most uses of them cause compiler segfaults or wrong code generation. EG... struct Move{ int D; } enum Move genMove = { D:4 }; immutable Move b = genMove; It's not difficult to fix these compiler problems, but I'm just not sure if it's worth implementing. Maybe they should just be dropped? (The { field: value } style anyway).Brought up in another thread, a good use of static initializers for structs: arrays of POD literals. For example: struct RGB { ubyte red, green, blue; } RGB[256] PALETTE = [ {0x00, 0x00, 0x00}, {0x01, 0x01, 0x01}, ... ]; can you do something like this without static initializers? My recollection is that this is the only way to have a struct array literal. -Steve
Dec 29 2009
Steven Schveighoffer:can you do something like this without static initializers? My recollection is that this is the only way to have a struct array literal.http://codepad.org/8HnF62s2 Bye, bearophile
Dec 29 2009
On Tue, 29 Dec 2009 15:02:50 -0500, bearophile <bearophileHUGS lycos.com> wrote:Steven Schveighoffer:OK, that makes sense. Last time I remember having issues with CTFE unless the static initializer was used, but that was on D1. -Stevecan you do something like this without static initializers? My recollection is that this is the only way to have a struct array literal.http://codepad.org/8HnF62s2
Dec 29 2009