digitalmars.D - Annoyance: 'Shadowing declaration is deprecated'+ mixins
- Don Clugston (12/12) Jul 24 2007 Is there any chance of getting the 'shadowing declaration is deprecated'...
- downs (10/27) Jul 24 2007 There's a workaround, but it's slightly perverted.
- downs (2/3) Jul 24 2007 Ahem. Degr_a_dation. Sorry.
- Bill Baxter (5/22) Jul 24 2007 I guess one obvious solution is to give your counter variables some
- Tristam MacDonald (2/25) Jul 24 2007 Hmm... This looks like a prime candidate for something like Scheme's 'ge...
- Pragma (14/40) Jul 24 2007 FWIW, there was a thread here a while back about generating unique value...
- BCS (26/42) Jul 24 2007 actually I couldn't get it working because I couldn't fake ++ under the ...
-
Stewart Gordon
(11/16)
Jul 25 2007
"Pragma"
wrote in message - Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (4/25) Jul 25 2007 Or extend templates to contain statements so you get three flies with on...
-
Don Clugston
(3/26)
Jul 24 2007
Yes. Although I don't like "likely"
. More difficult is the situation... - Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (9/26) Jul 25 2007 I hope that when macros come there will be a possibility to choose betwe...
- Don Clugston (4/32) Jul 25 2007 My post was actually to indicate that this lack of hygiene is a genuine ...
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (41/54) Jul 25 2007 Speaking of aesthetics makes it sound like it's only some academic nonse...
- Don Clugston (5/19) Jul 25 2007 Maybe. I hope macros can do it. It's going to be very hard to match the ...
Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.
Jul 24 2007
Don Clugston wrote:Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.There's a workaround, but it's slightly perverted. void main() { double i=300.0; () { mixin("for int i=0; i<10; ++i) { func(i); }"); }(); } This declares and calls a delegate in the same line, thereby establishing a distinct scope. Beware performance degredation though. --downs
Jul 24 2007
downs wrote:Beware performance degredation though.Ahem. Degr_a_dation. Sorry.
Jul 24 2007
Don Clugston wrote:Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I guess one obvious solution is to give your counter variables some names that are more likely to be unique: mixin("for (int __i8473=0; __i8473<10; ++__i8473) { func(__i8473); }"); --bb
Jul 24 2007
Bill Baxter Wrote:Don Clugston wrote:Hmm... This looks like a prime candidate for something like Scheme's 'gensym' call (which basically alliases an unique, un-named, and un-nameable symbol). Does anyone know of a way to accomplish the same at compile time in D?Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I guess one obvious solution is to give your counter variables some names that are more likely to be unique: mixin("for (int __i8473=0; __i8473<10; ++__i8473) { func(__i8473); }");
Jul 24 2007
Tristam MacDonald wrote:Bill Baxter Wrote:FWIW, there was a thread here a while back about generating unique values at compile time. In short, it's not possible (using pure D anyway) to maintain a state extrinsic to a set of template evaluations or CTFE calls. You need that property in order to guarantee uniqueness in your symbols by employing a counter variable to distinguish them. You have to either adopt some template warts to explicitly pass this state to every template/CTFE or use something outside D for all generated symbols to be unique. BCS (I think) suggested a rather elegant hack that uses a C preprocessor to work around this limitation. Another suggestion was to couple __LINE__ and __FILE__ to get *some* measure of uniqueness per-line. So it can be done, but it won't necessarily be pretty. It kinda makes me wish D had a __UNIQUE__ symbol (reliably unique for a given module/compilation unit?) for this kind of stuff. const char[] sym = __UNIQUE__; mixin("for (int " ~ sym ~ "=0; " ~ sym ~ "<10; ++" ~ sym ~ ") { func(" ~ sym ~ "); }"); -- - EricAnderton at yahooDon Clugston wrote:Hmm... This looks like a prime candidate for something like Scheme's 'gensym' call (which basically alliases an unique, un-named, and un-nameable symbol). Does anyone know of a way to accomplish the same at compile time in D?Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I guess one obvious solution is to give your counter variables some names that are more likely to be unique: mixin("for (int __i8473=0; __i8473<10; ++__i8473) { func(__i8473); }");
Jul 24 2007
Reply to Pragma,You have to either adopt some template warts to explicitly pass this state to every template/CTFE or use something outside D for all generated symbols to be unique. BCS (I think)guiltysuggested a rather elegant hack that uses a C preprocessor to work around this limitation.actually I couldn't get it working because I couldn't fake ++ under the preprocessorAnother suggestion was to couple __LINE__ and __FILE__ to get *some* measure of uniqueness per-line. So it can be done, but it won't necessarily be pretty.The final solution that worked used that (and some other entropy sources as well) |module uniq; | |const char[] prefix = ""; |pragma(msg, prefix~"module uniq;") | |/** use this template as a unique uint | | make sure that each usage has a unique string (__FILE__":"~itoa!(__LINE__) is a good starting point) | | compile the program once, filter the output for lines that start with prefix and then recompile with that output replacing this file. |*/ |template UniqID(char[] str) |{ | const uint UniqID = 0; | pragma(msg, "template UniqID(char[] str : \""~str~"\") {const uint UniqID = __LINE__;}") |}It kinda makes me wish D had a __UNIQUE__ symbol (reliably unique for a given module/compilation unit?) for this kind of stuff. const char[] sym = __UNIQUE__; mixin("for (int " ~ sym ~ "=0; " ~ sym ~ "<10; ++" ~ sym ~ ") { func(" ~ sym ~ "); }");make it a GUID... and have fun debugging _e4f74de910de478b8a8c7f79b92f8459(int _53e2b8bd63534fafbf3a0fe5caa955b4, float _f1e57ba407ba4b4185cb41f6b902f1cd)
Jul 24 2007
"Pragma" <ericanderton yahoo.removeme.com> wrote in message news:f85gh5$g8l$1 digitalmars.com... <snip>It kinda makes me wish D had a __UNIQUE__ symbol (reliably unique for a given module/compilation unit?) for this kind of stuff. const char[] sym = __UNIQUE__; mixin("for (int " ~ sym ~ "=0; " ~ sym ~ "<10; ++" ~ sym ~ ") { func(" ~ sym ~ "); }");Why create a workaround for this language deficiency rather than fixing it? http://www.digitalmars.com/d/pretod.html#mixins "Mixins create a scope, macros do not." "Mixins automatically create unique identifiers as required using a standard algorithm, macros have to do it manually with kludgy token pasting." This of course applies to template mixins. But why not make these points apply to text mixins just the same? Stewart.
Jul 25 2007
Stewart Gordon wrote:"Pragma" <ericanderton yahoo.removeme.com> wrote in message news:f85gh5$g8l$1 digitalmars.com... <snip>Or extend templates to contain statements so you get three flies with one hit: macros, a fix to this problem & syntax highlighting back. Well, not completely, but the other deficiencies should be obvious by then.It kinda makes me wish D had a __UNIQUE__ symbol (reliably unique for a given module/compilation unit?) for this kind of stuff. const char[] sym = __UNIQUE__; mixin("for (int " ~ sym ~ "=0; " ~ sym ~ "<10; ++" ~ sym ~ ") { func(" ~ sym ~ "); }");Why create a workaround for this language deficiency rather than fixing it? http://www.digitalmars.com/d/pretod.html#mixins "Mixins create a scope, macros do not." "Mixins automatically create unique identifiers as required using a standard algorithm, macros have to do it manually with kludgy token pasting." This of course applies to template mixins. But why not make these points apply to text mixins just the same?
Jul 25 2007
Bill Baxter wrote:Don Clugston wrote:Yes. Although I don't like "likely" <g>. More difficult is the situation when the mixin is recursive. Each nested level needs to use a different name.Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I guess one obvious solution is to give your counter variables some names that are more likely to be unique: mixin("for (int __i8473=0; __i8473<10; ++__i8473) { func(__i8473); }");
Jul 24 2007
Don Clugston wrote:Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I hope that when macros come there will be a possibility to choose between hygienic and unhygienic versions. I've started to think string mixins are a big design mistake. Looking at those compile time unique id hacks from Lisp coder's POV it's amazing to see how badly you can implement something so obvious. I wrote about macros a while ago and noticed that by increasing the power of template mixins and alias parameters it would be possible to achieve the same things and more without sacrificing e.g. syntactical transparency.
Jul 25 2007
Jari-Matti Mäkelä wrote:Don Clugston wrote:My post was actually to indicate that this lack of hygiene is a genuine nuisance (not merely aesthetically undesirable). I wonder when an unhygienic macro would actually be useful.Is there any chance of getting the 'shadowing declaration is deprecated' error message disabled, for code inserted via a mixin? It means that if you inject a 'for' loop into the current function, it appears to work, but will fail if another variable with the same name already exists. void main() { // double i=300.0; mixin("for (int i=0; i<10; ++i) { func(i); }"); } When such code is generated by a mixin, the shadowing does not indicate a probable error. This is proving to be quite annoying for my BLADE rewrite.I hope that when macros come there will be a possibility to choose between hygienic and unhygienic versions. I've started to think string mixins are a big design mistake. Looking at those compile time unique id hacks from Lisp coder's POV it's amazing to see how badly you can implement something so obvious. I wrote about macros a while ago and noticed that by increasing the power of template mixins and alias parameters it would be possible to achieve the same things and more without sacrificing e.g. syntactical transparency.
Jul 25 2007
Don Clugston wrote:Jari-Matti Mäkelä wrote:Speaking of aesthetics makes it sound like it's only some academic nonsense not applicable in "real world". I've experienced the same problems even with very short metaprograms and created ugly looking ad-hoc workarounds. Most other languages solve the problem using similar techniques so I just wanted to tell there's no need to reimplement the wheel this time. This is a bad example, but hopefully highlights some of the problems with current constructs: import tango.io.Stdout; char[] a, i; char[] foo(char[] a) { return "for (int i=0; i<"~a~".length;i++) Stdout("~a~"[i]).newline;"; } mixin GenNewUniqPrefix!(); // defined elsewhere char[] ad_hoc_foo(char[] a) { char[] safe_prefix = getLastUniqPrefix(); // defined elsewhere char[] safe_a = safe_prefix ~ "a"; char[] safe_i = safe_prefix ~ "i"; return "for (int "~safe_i~"=0; i<"~safe_a ~".length;"~safe_i~"++) Stdout("~safe_a~"["~safe_i~"]).newline;"; } template hygienic_foo(alias a) { void hygienic_foo() { for(int i=0; i<a.length; i++) Stdout(a[i]).newline; } } /* not implemented yet macro macro_foo(alias a) { for(int i=0; i<a.length; i++) Stdout(a[i]).newline; } */ void main() { int[3] bar = [1,2,3]; class i {} mixin(foo("bar")); // collision hygienic_foo!(bar)(); macro_foo(bar); // not implemented yet }I hope that when macros come there will be a possibility to choose between hygienic and unhygienic versions. I've started to think string mixins are a big design mistake. Looking at those compile time unique id hacks from Lisp coder's POV it's amazing to see how badly you can implement something so obvious. I wrote about macros a while ago and noticed that by increasing the power of template mixins and alias parameters it would be possible to achieve the same things and more without sacrificing e.g. syntactical transparency.My post was actually to indicate that this lack of hygiene is a genuine nuisance (not merely aesthetically undesirable). I wonder when an unhygienic macro would actually be useful.
Jul 25 2007
Jari-Matti Mäkelä wrote:Don Clugston wrote:Yup. I've heard "hygienic" used as if it was purely academic. It's certainly not.Jari-Matti Mäkelä wrote:Speaking of aesthetics makes it sound like it's only some academic nonsense not applicable in "real world".I hope that when macros come there will be a possibility to choose between hygienic and unhygienic versions. I've started to think string mixins are a big design mistake.My post was actually to indicate that this lack of hygiene is a genuine nuisance (not merely aesthetically undesirable). I wonder when an unhygienic macro would actually be useful.Most other languages solve the problem using similar techniques so I just wanted to tell there's no need to reimplement the wheel this time.Maybe. I hope macros can do it. It's going to be very hard to match the power of mixins, though. In particular, the case where symbol names are embedded in a string seems to be useful, important, and difficult.
Jul 25 2007