digitalmars.D - PHP-style (embedded variables) print statements
- Don Clugston (27/27) May 31 2007 With CTFE and text mixins, it is now reasonably straightforward to
- Jarrett Billingsley (8/13) May 31 2007 You can't print out the string using %s?
- Don Clugston (14/30) May 31 2007 The problem is that it's so easy to forget the %s, and have a latent bug...
- Lars Ivar Igesund (15/50) May 31 2007 To compare, you should use
- Don Clugston (7/54) May 31 2007 It's all possible. And that mountain of localisation stuff would not be ...
- Dejan Lekic (1/2) May 31 2007
- Bent Rasmussen (3/5) Jun 01 2007 Agreed. The Phobos and Tango methods are highly readable.
- Sean Kelly (11/15) Jun 01 2007 I think the Phobos syntax could probably be added to Tango using
- Don Clugston (8/25) Jun 02 2007 Unfortunately, that adds template bloat, since every combination of type...
- Gregor Richards (3/7) Jun 01 2007 Are you kidding me? This is the most readable syntax available in D to d...
- Leandro Lucarella (12/17) Jun 02 2007 It still sucks =/
- Daniel Keep (12/16) Jun 01 2007 "Mummy, why are my eyes bleeding?"
- Bill Baxter (5/23) May 31 2007 That's pretty cool. I would probably use that over other alternatives,
- Witold Baryluk (6/6) May 31 2007 http://smp.if.uj.edu.pl/~baryluk/d/echo/echo.d
- Don Clugston (8/10) May 31 2007 We're obviously thinking the same way!
- Ary Manzana (2/164) May 31 2007
- Robert Fraser (2/4) May 31 2007 Yes; it just transforms the expression into a printf() call.
- Unknown W. Brackets (4/39) Jun 01 2007 I hate it when people use this in PHP and Perl, it can be un-greppable a...
- Don Clugston (5/16) Jun 02 2007 This is a really important problem. I think it is relevant to almost any...
- Unknown W. Brackets (5/23) Jun 05 2007 That becomes impractical when you have real-time code completion to deal...
- Robert Fraser (2/11) Jun 02 2007
- Dejan Lekic (1/1) Jun 03 2007 IMHO both implementations are really fine. As someone asked above - is i...
- Don Clugston (7/8) Jun 03 2007 AFAIK, it's not possible to eliminate the mixin() yet. But, it will defi...
With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner. For example, the attached code (rough draft) allows you to write things like: int i; const k = 8; char [] str; mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str\n")); which is typesafe, converts all compile-time constants directly into the format string, and converts everything else into a simple printf() call. The mixin line above becomes printf("current=%d next=%d const=24 %.*s\n", i, i+1, str); Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character). Incidentally, this could do a lot better than printf, because it could categorise the expressions. Eg, if there are no floating point variables, it could translate it to a simple print function which doesn't have the FP conversion code. Ditto for outputting arrays and objects. Other optimisations are possible - eg, it could also estimate how much buffer space is going to be required. Downsides: (1) need to use "mixin()" until we get macros. (2) doesn't look like anything that's in D right now. (3) how are IDE's going to know when a string contains embedded variables? Opinions? Is something like this worth considering as an alternative to
May 31 2007
"Don Clugston" <dac nospam.com.au> wrote in message news:f3lt8d$2je5$1 digitalmars.com...Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character).You can't print out the string using %s?Opinions? Is something like this worth considering as an alternative toNot to burst your bubble, but I've just never found variable interpolation to be all that useful, mostly because it's not really obvious (unless you have some kind of fancy code highlighter) when something's being interpolated, and because there's already syntaxes that look fine to me. Some people like it though.
May 31 2007
Jarrett Billingsley wrote:"Don Clugston" <dac nospam.com.au> wrote in message news:f3lt8d$2je5$1 digitalmars.com...The problem is that it's so easy to forget the %s, and have a latent bug that lies undetected.Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character).You can't print out the string using %s?Yes, these are the main issues. I know that people have requested it in the past (and it was also touted as something Nemerle can do which D can't <g>). Personally, I thought it was one of very few interesting features of PHP. There's probably a syntax which would be a bit more obvious, but still... mixin interpolation: mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str")); print("current={0} next={1} const={2} {3}", i, i+1, k+3, str)); Phobos: writef("current=", i, " next=", i+1, " const=", k+3, " ", str);Opinions? Is something like this worth considering as an alternative toNot to burst your bubble, but I've just never found variable interpolation to be all that useful, mostly because it's not really obvious (unless you have some kind of fancy code highlighter) when something's being interpolated, and because there's already syntaxes that look fine to me. Some people like it though.
May 31 2007
Don Clugston wrote:Jarrett Billingsley wrote:To compare, you should use Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str); Since I'm not too happy about $vars , I would find it more interesting if it was mixin(dprint("current={i} next={i+1,5} const={k*3:C} {str})); print as currency (:C). Even more interesting would be to use Sprint to make it usable in logging. Would have to get rid of the mixin, though :) -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango"Don Clugston" <dac nospam.com.au> wrote in message news:f3lt8d$2je5$1 digitalmars.com...The problem is that it's so easy to forget the %s, and have a latent bug that lies undetected.Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character).You can't print out the string using %s?Yes, these are the main issues. I know that people have requested it in the past (and it was also touted as something Nemerle can do which D can't <g>). Personally, I thought it was one of very few interesting features of PHP. There's probably a syntax which would be a bit more obvious, but still... mixin interpolation: mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str")); print("current={0} next={1} const={2} {3}", i, i+1, k+3, str));Opinions? Is something like this worth considering as an alternative toNot to burst your bubble, but I've just never found variable interpolation to be all that useful, mostly because it's not really obvious (unless you have some kind of fancy code highlighter) when something's being interpolated, and because there's already syntaxes that look fine to me. Some people like it though.
May 31 2007
Lars Ivar Igesund wrote:Don Clugston wrote:It's all possible. And that mountain of localisation stuff would not be linked in, if it was never used in any format strings. The :C syntax might be confusing, though, because it looks like the ?: operator. "const={b?c:C:C}" Even more interesting would be to use Sprint toJarrett Billingsley wrote:To compare, you should use Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str); Since I'm not too happy about $vars , I would find it more interesting if it was mixin(dprint("current={i} next={i+1,5} const={k*3:C} {str})); print as currency (:C)."Don Clugston" <dac nospam.com.au> wrote in message news:f3lt8d$2je5$1 digitalmars.com...The problem is that it's so easy to forget the %s, and have a latent bug that lies undetected.Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character).You can't print out the string using %s?Yes, these are the main issues. I know that people have requested it in the past (and it was also touted as something Nemerle can do which D can't <g>). Personally, I thought it was one of very few interesting features of PHP. There's probably a syntax which would be a bit more obvious, but still... mixin interpolation: mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str")); print("current={0} next={1} const={2} {3}", i, i+1, k+3, str));Opinions? Is something like this worth considering as an alternative toNot to burst your bubble, but I've just never found variable interpolation to be all that useful, mostly because it's not really obvious (unless you have some kind of fancy code highlighter) when something's being interpolated, and because there's already syntaxes that look fine to me. Some people like it though.make it usable in logging.Should be trivial.Would have to get rid of the mixin, though :)
May 31 2007
I pray to God I will never have to write code like:Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
May 31 2007
Agreed. The Phobos and Tango methods are highly readable. "Dejan Lekic" <dejan.lekic gmail.com> wrote in message news:f3ngam$2d4b$1 digitalmars.com...I pray to God I will never have to write code like:Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 01 2007
Dejan Lekic wrote:I pray to God I will never have to write code like:I think the Phobos syntax could probably be added to Tango using variadic templates: void opCall( Args... )( Args args ) { foreach( arg; args ) this.print( arg ); } Something like that. But I personally don't find the "whisper" syntax to be particularly annoying. SeanStdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 01 2007
Sean Kelly wrote:Dejan Lekic wrote:Unfortunately, that adds template bloat, since every combination of types gets its own instantation... But I personally don't find the "whisper" syntaxI pray to God I will never have to write code like:I think the Phobos syntax could probably be added to Tango using variadic templates: void opCall( Args... )( Args args ) { foreach( arg; args ) this.print( arg ); } Something like that.Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);to be particularly annoying.I don't like it myself, but aside from macros/mixins it's the only typesafe option not requiring RTTI or template bloat. With macros, we should be able to do much the same thing with writefln syntax. (ie, convert it to a sequence of whisper calls).
Jun 02 2007
Dejan Lekic wrote:I pray to God I will never have to write code like:Are you kidding me? This is the most readable syntax available in D to date. - Gregor RichardsStdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 01 2007
Gregor Richards, el 1 de junio a las 12:11 me escribiste:Dejan Lekic wrote:It still sucks =/ I'm sorry, I don't want to troll, but I think event printf() has a much nicer syntax. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ .------------------------------------------------------------------------, \ GPG: 5F5A8D05 // F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05 / '--------------------------------------------------------------------' "Lidiar" no es lo mismo que "holguear"; ya que "lidiar" es relativo a "lidia" y "holguear" es relativo a "olga". -- Ricardo VaporesoI pray to God I will never have to write code like:Are you kidding me? This is the most readable syntax available in D to date.Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 02 2007
Dejan Lekic wrote:I pray to God I will never have to write code like:"Mummy, why are my eyes bleeding?" -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/Stdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 01 2007
Don Clugston wrote:With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner. For example, the attached code (rough draft) allows you to write things like: int i; const k = 8; char [] str; mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str\n"));...Downsides: (1) need to use "mixin()" until we get macros. (2) doesn't look like anything that's in D right now. (3) how are IDE's going to know when a string contains embedded variables? Opinions? Is something like this worth considering as an alternative toThat's pretty cool. I would probably use that over other alternatives, but not if it requires the mixin(...) syntax to use. --bb
May 31 2007
http://smp.if.uj.edu.pl/~baryluk/d/echo/echo.d http://smp.if.uj.edu.pl/~baryluk/d/echo/echo.html -- Witold Baryluk MAIL: baryluk smp.if.uj.edu.pl, baryluk mpi.int.pl JID: movax jabber.autocom.pl
May 31 2007
Witold Baryluk wrote:http://smp.if.uj.edu.pl/~baryluk/d/echo/echo.d http://smp.if.uj.edu.pl/~baryluk/d/echo/echo.htmlWe're obviously thinking the same way! Yours is better presented than mine. I use a significant trick, though: the text which gets mixed in, contains a _second_ mixin. This allows the CTFE function to know the type of each variable, and its value if it is a compile-time constant. (although use of the value is currently incomplete, and disabled in the code I posted). Consequently, my version does not require RTTI (yours does, inside writefln). Feel free to steal ideas from it.
May 31 2007
Can this be used for non-constant values? Don Clugston escribió:With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner. For example, the attached code (rough draft) allows you to write things like: int i; const k = 8; char [] str; mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str\n")); which is typesafe, converts all compile-time constants directly into the format string, and converts everything else into a simple printf() call. The mixin line above becomes printf("current=%d next=%d const=24 %.*s\n", i, i+1, str); Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character). Incidentally, this could do a lot better than printf, because it could categorise the expressions. Eg, if there are no floating point variables, it could translate it to a simple print function which doesn't have the FP conversion code. Ditto for outputting arrays and objects. Other optimisations are possible - eg, it could also estimate how much buffer space is going to be required. Downsides: (1) need to use "mixin()" until we get macros. (2) doesn't look like anything that's in D right now. (3) how are IDE's going to know when a string contains embedded variables? Opinions? Is something like this worth considering as an alternative to ------------------------------------------------------------------------ module DPrint; /// Convert an integer of type T to string. /// Note: this function is CTFE-compatible, but not very efficient at runtime char [] ct_itoa(T)(T x) { char [] s=""; static if (is(T==byte)||is(T==short)||is(T==int)||is(T==long)) { if (x<0) { s = "-"; x = -x; } } do { s = cast(char)('0' + (x%10)) ~ s; x/=10; } while (x>0); return s; } // Templates to return string representation of floating-point constant. // This works, but only for floating-point constants -- should really create a // CTFE-compatible ftoa(). char [] mixin_ftoa(real x)() { return `"` ~ x.stringof ~ `"`; } char [] mixin_ftoa(ireal x)() { return `"` ~ x.stringof ~ `"`; } char [] mixin_ftoa(creal x)() { return `"` ~ x.stringof ~ `"`; } /** Evaluate a textual expression of type T, and return it as a textual literal. * */ char [] dollar_convert(T)(char [] x) { static if (is(T ==long)) return `"%Ld"`; else static if (is(T==ulong)) return `"%Lu"`; else static if (is(T:int)) return `"%d"`; else static if (is(T:uint)) return `"%u"`; else static if (is(T==real)) return `"%Lg"`; else static if (is(T:double)) return `"%g"`; else static if (is(T==char[])) return `"%.*s"`; else return x; } private { // BUGS: Many other UTF chars should be allowed inside identifiers. bool isIdentifierChar(char c) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c=='_'); } } /** Evaluate a string containing embedded 'dollar expressions'. * * Given a string containing embedded expression marked with 'dollar' indicators, * returns a string which, when mixed in, will evaluate to a new string with all * of the expressions evaluated. * The expressions can be strings, or any integral type, or a floating-point * constant (real, imaginary or complex) expression. * Dollar expressions consist of a dollar sign, followed by a variable name * (the first non-identifier character marks the end), or a dollar sign followed * by an expression in parentheses. Two consecutive dollar signs become a dollar * character. */ char [] dprint(char [] s) { char [] result=`printf(("`; char [] vars=""; int i=0; while (i<s.length) { if (i<s.length-1 && s[i]=='$') { if (s[i+1]=='$') { result~='$'; // replace "$$" with '$'. i+=2; } else { // replace "$expression" with the expression int start=i+1; int parenCount=0; if (s[start]=='(') { ++start; parenCount++; } for (i=start; i<s.length; ++i) { if (s[i]=='(') ++parenCount; if (s[i]==')') { --parenCount; if (parenCount==0) break; } if (parenCount==0 && !isIdentifierChar(s[i])) break; } // Evaluate the expression, and convert it to a string vars ~="," ~ s[start..i]; result ~= `"~mixin(dollar_convert!(typeof(` ~ s[start..i] ~ `))("` ~ s[start..i] ~ `"))~"`; if (s[i]==')') ++i; } } else { if (s[i]=='"') result ~= `\"`; // Retain embedded quotes. else result ~= s[i]; ++i; } } return result~ `").ptr`~vars ~ `);`; } //----------------- // Example void main() { int k=56; const int k2=7; const double q = 4.1432e58; const q2 = 4.1432e58; char [] x ="this is a string"; const x2 ="this is a const string"; mixin(dprint(`The value of q2 is: $(q2*7) and k dollars is $$$k, but k2 is $k2 followed by $(k2 *5+1) and the floating point expression is $(q*2.18), string x is: $x and $x2 `)); }
May 31 2007
Ary Manzana Wrote:Can this be used for non-constant values?Yes; it just transforms the expression into a printf() call.
May 31 2007
I hate it when people use this in PHP and Perl, it can be un-greppable and there's so much ambiguity when using arrays and similar. Still, pretty cool to be able to do it in D. Just shows D's strengths. -[Unknown] Don Clugston Wrote:With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner. For example, the attached code (rough draft) allows you to write things like: int i; const k = 8; char [] str; mixin(dprint("current=$i next=$(i+1) const=$(k*3) $str\n")); which is typesafe, converts all compile-time constants directly into the format string, and converts everything else into a simple printf() call. The mixin line above becomes printf("current=%d next=%d const=24 %.*s\n", i, i+1, str); Note that unlike a tuple solution, it does not cause any template bloat. Also doesn't have some of writefln's pitfalls (the case where a string contains a % character). Incidentally, this could do a lot better than printf, because it could categorise the expressions. Eg, if there are no floating point variables, it could translate it to a simple print function which doesn't have the FP conversion code. Ditto for outputting arrays and objects. Other optimisations are possible - eg, it could also estimate how much buffer space is going to be required. Downsides: (1) need to use "mixin()" until we get macros. (2) doesn't look like anything that's in D right now. (3) how are IDE's going to know when a string contains embedded variables? Opinions? Is something like this worth considering as an alternative to
Jun 01 2007
Unknown W. Brackets wrote:I hate it when people use this in PHP and Perl, it can be un-greppableThis is a really important problem. I think it is relevant to almost any domain-specific language. (Find all references to variable xxx). Inside an IDE, you could theoretically grep on the source the compiler sees after mixins are evaluated, but it's pretty nasty otherwise.and there's so much ambiguity when using arrays and similar. Still, pretty cool to be able to do it in D. Just shows D's strengths. -[Unknown] Don Clugston Wrote:With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner.
Jun 02 2007
That becomes impractical when you have real-time code completion to deal with (example: struct.member... "$struct.member" should then work too but it's unlikely to be practical to figure that per keystroke.) -[Unknown] Don Clugston wrote:Unknown W. Brackets wrote:I hate it when people use this in PHP and Perl, it can be un-greppableThis is a really important problem. I think it is relevant to almost any domain-specific language. (Find all references to variable xxx). Inside an IDE, you could theoretically grep on the source the compiler sees after mixins are evaluated, but it's pretty nasty otherwise.and there's so much ambiguity when using arrays and similar. Still, pretty cool to be able to do it in D. Just shows D's strengths. -[Unknown] Don Clugston Wrote:With CTFE and text mixins, it is now reasonably straightforward to implement PHP-style 'dollar' embedded variables, in a type-safe manner.
Jun 05 2007
I'm not sure if you're being sarcastic, but if you're not, I agree - it's nicely spaced with clear delimiters. Gregor Richards Wrote:Dejan Lekic wrote:I pray to God I will never have to write code like:Are you kidding me? This is the most readable syntax available in D to date. - Gregor RichardsStdout("current=")(i)(" next=")(i+1)(" const=")(k*3)(" ")(str);
Jun 02 2007
IMHO both implementations are really fine. As someone asked above - is it possible to avoid mixin(echo(...)) somehow, and have nice and clean echo("Blah $(var+1) blah") ? It would be totally awesome, I think.
Jun 03 2007
Dejan Lekic wrote:IMHO both implementations are really fine. As someone asked above - is it possible to avoid mixin(echo(...)) somehow, and have nice and clean echo("Blah $(var+1) blah") ? It would be totally awesome, I think.AFAIK, it's not possible to eliminate the mixin() yet. But, it will definitely be possible with macros. There's a lot of 'low-lying fruit' for macros -- even the tiniest bit of syntax sugar will make usage of this kind of code almost perfect. The nice thing is, that we don't need to postulate about what will be possible with AST macros -- we can develop the code already. It's just got these messy 'mixin()'s all over it. <g>.
Jun 03 2007