digitalmars.D - Convenient debug printing
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (24/24) Feb 01 2019 Rust just added a standard macro `dbg` for debug printing
- Jacob Carlborg (5/6) Feb 01 2019 No, not if you want it to print the variable name. Yet another case for
- 12345swordy (4/9) Feb 01 2019 I am pretty sure that the universe will freeze-over, before
- Meta (10/13) Feb 01 2019 Meaning no offense to Walter, his recent statements on the AST
- JN (3/4) Feb 01 2019 What's the difference between C #define and stitching strings
- Adam D. Ruppe (5/7) Feb 01 2019 those ~ strings can only be stitched to other strings, not to the
- jmh530 (14/24) Feb 01 2019 In general, the rvalue DIP makes pretty clear that Walter and
- Olivier FAURE (31/39) Feb 02 2019 While you're being more charitable than most people I've seen on
- Jacob Carlborg (9/18) Feb 02 2019 All of the old DIPs (on the wiki) are written in a completely different
- Neia Neutuladh (17/22) Feb 01 2019 From what I've read, Rust macros allow you to define new syntax:
- Dmitry (3/4) Feb 01 2019 It looks interesting. Why didn't it go?
- Jacob Carlborg (7/10) Feb 02 2019 It was never formally put through a process. Not sure if we had a
- Neia Neutuladh (4/7) Feb 02 2019 It looks incomplete. It doesn't even begin to explain what sort of objec...
- Jacob Carlborg (7/10) Feb 04 2019 It's far from complete. As I mentioned elsewhere, the DIPs on the wiki
- Jacob Carlborg (4/6) Feb 02 2019 Yeah, I know :(.
- Rubn (8/32) Feb 01 2019 import std.stdio;
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (5/9) Feb 01 2019 Nice!
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (2/4) Feb 01 2019 Ahh, of course, I returns the symbol name as a `string`.
- ezneh (32/42) Feb 01 2019 I got this working without using the alias a, but working with
- Olivier FAURE (8/15) Feb 02 2019 I did think it was weird that a similar result couldn't be
- Olivier FAURE (4/5) Feb 02 2019 Or adding a new "expressionString" trait applicable to aliases
-
Patrick Schluter
(5/8)
Feb 02 2019
What's wrong with `debug log(
);` from - Jacob Carlborg (5/9) Feb 02 2019 I think what's missing is the variable name not being automatically
- Gary Willoughby (5/15) Feb 02 2019 This!
- ezneh (72/73) Feb 02 2019 Alright, after quite some work I finally managed to do the
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (3/8) Feb 03 2019 Great! Close enough for me!
- =?iso-8859-1?Q?Robert_M._M=FCnch?= (8/16) Nov 17 2019 This looks great, but I get:
Rust just added a standard macro `dbg` for debug printing https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#the-dbg-macro What's the closest match for this macro we can get with D? I have put together a similar solution at https://github.com/nordlow/phobos-next/blob/master/src/dbgio.d#L51 used as int x = 42; dbg("x: ", x); printing dbgio.d:68: Info: x: 42 but it only works with a cumbersome writeln-syntax. I also have https://github.com/nordlow/phobos-next/blob/master/src/dbgio.d#L12 copied from Wilzbach's effort and used as int x = 42; int[] y = [42, 43]; mixin dump!("x", "y"); printing dbgio.d:17: Info: x: 42, y: [42, 43] but, of course, cumbersome in another syntactic way. Is this as good as it gets in D with regards to syntactic sugarness?
Feb 01 2019
On 2019-02-01 16:49, Per Nordlöw wrote:Is this as good as it gets in D with regards to syntactic sugarness?No, not if you want it to print the variable name. Yet another case for AST macros. -- /Jacob Carlborg
Feb 01 2019
On Friday, 1 February 2019 at 19:34:30 UTC, Jacob Carlborg wrote:On 2019-02-01 16:49, Per Nordlöw wrote:I am pretty sure that the universe will freeze-over, before Walter consider AST macros. -AlexIs this as good as it gets in D with regards to syntactic sugarness?No, not if you want it to print the variable name. Yet another case for AST macros.
Feb 01 2019
On Friday, 1 February 2019 at 20:32:54 UTC, 12345swordy wrote:I am pretty sure that the universe will freeze-over, before Walter consider AST macros. -AlexMeaning no offense to Walter, his recent statements on the AST macros makes me think that he is mistaking what Jacob has proposed before (Lisp or Rust-style hygienic AST macros) for C-style text macros (which are, of course, supremely terrible). His main argument, about not wanting people to be able to invent their own syntax and encourage fragmentation within the language community, does not ring true. All you have to do is look at Rust to see that it is possible to support a limited form of AST macro without any adverse effects.
Feb 01 2019
On Friday, 1 February 2019 at 21:40:29 UTC, Meta wrote:C-style text macros (which are, of course, supremely terrible).What's the difference between C #define and stitching strings with ~ all over the place?
Feb 01 2019
On Friday, 1 February 2019 at 21:48:18 UTC, JN wrote:What's the difference between C #define and stitching strings with ~ all over the place?those ~ strings can only be stitched to other strings, not to the rest of the program. mixin operates as complete blocks (it inserts AST nodes, not code per se). of course you could say the same thing about ast macros lol
Feb 01 2019
On Friday, 1 February 2019 at 21:40:29 UTC, Meta wrote:[snip] Meaning no offense to Walter, his recent statements on the AST macros makes me think that he is mistaking what Jacob has proposed before (Lisp or Rust-style hygienic AST macros) for C-style text macros (which are, of course, supremely terrible). His main argument, about not wanting people to be able to invent their own syntax and encourage fragmentation within the language community, does not ring true. All you have to do is look at Rust to see that it is possible to support a limited form of AST macro without any adverse effects.In general, the rvalue DIP makes pretty clear that Walter and Andrei have a high bar for the quality of a DIP, particularly one that could have a big impact on the language. I don't think the old AST macro DIP is probably up to the standard that would be needed at this point regardless. It would need a re-work and definitely need to be written from the perspective of convincing W&A, which is a pretty high hurdle given their biases. Two of the interesting things about AST macros to me are 1) that it seems pretty straightforward to implement C++'s metaclass proposal using them, 2) not only could a lot of D's other features like foreach be written in terms of them but a lot of the attributes could too. This could enable a lot of customization, which could be good or bad...
Feb 01 2019
On Friday, 1 February 2019 at 23:50:04 UTC, jmh530 wrote:In general, the rvalue DIP makes pretty clear that Walter and Andrei have a high bar for the quality of a DIP, particularly one that could have a big impact on the language. I don't think the old AST macro DIP is probably up to the standard that would be needed at this point regardless. It would need a re-work and definitely need to be written from the perspective of convincing W&A, which is a pretty high hurdle given their biases.While you're being more charitable than most people I've seen on the forum, I think this isn't a constructive approach to dealing with language maintainers. A lot of people on the forum are essentially treating the maintainers as living obstacles to be worked around, not people to work with, which: - Is kind of disrespectful in the first place. - Excludes them from the discussion, instead of trying to improve communication. - Asks the wrong question: "How can we convince them?" instead of "What is best for the language, and how does that overlap with their opinion?" I'm not saying they're always right, mind you. But to get back to AST macros, I think it would be more constructive to look at the positive aspects of macros, the intended use cases, examples from other languages where macros are useful, etc... and *also* look at their drawbacks, investigate the problems they can create, probably ask Walter and Andrei for an exhaustive list of objections, ideally examples of problematic code... Then, when it comes to writing a DIP, try to propose something that covers the intended use cases in an elegant way *without* hitting the drawbacks they're worried about. The DIP shouldn't be "That thing you already refused except this time it's going to convince you despite your biases!", because that's not an intellectually honest way to proceed. I don't think I'm saying anything crazy either. Most use cases for AST macros in other languages are already covered by D's template system. It might be possible to get the most popular use cases (eg smart assertions) by just giving templates more power.
Feb 02 2019
On 2019-02-02 00:50, jmh530 wrote:It would need a re-work and definitely need to be written from the perspective of convincing W&A, which is a pretty high hurdle given their biases.All of the old DIPs (on the wiki) are written in a completely different style. Back then the requirements to get a DIP passed was a lot less then it is now. Those DIP are not really written like a spec. On the other hand the D spec is not written like a spec either :).Two of the interesting things about AST macros to me are 1) that it seems pretty straightforward to implement C++'s metaclass proposal using themYes, I think so.2) not only could a lot of D's other features like foreach be written in terms of them but a lot of the attributes could too. This could enable a lot of customization, which could be good or bad...Yes, exactly. -- /Jacob Carlborg
Feb 02 2019
On Fri, 01 Feb 2019 21:40:29 +0000, Meta wrote:His main argument, about not wanting people to be able to invent their own syntax and encourage fragmentation within the language community, does not ring true. All you have to do is look at Rust to see that it is possible to support a limited form of AST macro without any adverse effects.From what I've read, Rust macros allow you to define new syntax: let fib = recurrence![ a[n]: u64 = 0, 1 ... a[n-1] + a[n-2] ]; credit: https://danielkeep.github.io/practical-intro-to-macros.html That "..." isn't a Rust language construct; it's defined by the macro (and only works within the macro's arguments, so you can't do a Pascal-in-C style `#define begin {`). like database libraries that take normal lambdas. They're sufficient for writing an assertion tool that can take an expression, evaluate it, and print out every part of it for analysis if something went wrong. An old DIP <https://wiki.dlang.org/DIP50> for AST macros in D suggests this strategy, along with implicit stringification of block statements belonging to a macro invocation and access to the context of the invocation. That probably shouldn't be necessary to do a lot of weird and wonderful things. But it's not going to happen.
Feb 01 2019
On Saturday, 2 February 2019 at 05:20:50 UTC, Neia Neutuladh wrote:An old DIP <https://wiki.dlang.org/DIP50> for AST macros in DIt looks interesting. Why didn't it go?
Feb 01 2019
On 2019-02-02 08:24, Dmitry wrote:On Saturday, 2 February 2019 at 05:20:50 UTC, Neia Neutuladh wrote:It was never formally put through a process. Not sure if we had a process back then for DIPs. Originally it was just me writing down what I though AST macros would be like in a single place, to avoid having to repeat long explanations on the forums. -- /Jacob CarlborgAn old DIP <https://wiki.dlang.org/DIP50> for AST macros in DIt looks interesting. Why didn't it go?
Feb 02 2019
On Sat, 02 Feb 2019 07:24:45 +0000, Dmitry wrote:On Saturday, 2 February 2019 at 05:20:50 UTC, Neia Neutuladh wrote:It looks incomplete. It doesn't even begin to explain what sort of object model the compiler should expose, and it has a block-to-string feature that it doesn't really talk about in any detail.An old DIP <https://wiki.dlang.org/DIP50> for AST macros in DIt looks interesting. Why didn't it go?
Feb 02 2019
On 2019-02-02 18:23, Neia Neutuladh wrote:It looks incomplete. It doesn't even begin to explain what sort of object model the compiler should expose, and it has a block-to-string feature that it doesn't really talk about in any detail.It's far from complete. As I mentioned elsewhere, the DIPs on the wiki are from a different time with not as high standards. It was also never formally reviewed, it was more that I wrote down what I though AST macros should be like to avoiding having to repeat myself on the forums. -- /Jacob Carlborg
Feb 04 2019
On 2019-02-01 21:32, 12345swordy wrote:I am pretty sure that the universe will freeze-over, before Walter consider AST macros.Yeah, I know :(. -- /Jacob Carlborg
Feb 02 2019
On Friday, 1 February 2019 at 15:49:24 UTC, Per Nordlöw wrote:Rust just added a standard macro `dbg` for debug printing https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#the-dbg-macro What's the closest match for this macro we can get with D? I have put together a similar solution at https://github.com/nordlow/phobos-next/blob/master/src/dbgio.d#L51 used as int x = 42; dbg("x: ", x); printing dbgio.d:68: Info: x: 42 but it only works with a cumbersome writeln-syntax. I also have https://github.com/nordlow/phobos-next/blob/master/src/dbgio.d#L12 copied from Wilzbach's effort and used as int x = 42; int[] y = [42, 43]; mixin dump!("x", "y"); printing dbgio.d:17: Info: x: 42, y: [42, 43] but, of course, cumbersome in another syntactic way. Is this as good as it gets in D with regards to syntactic sugarness?import std.stdio; void dbg(alias a)(string file = __FILE__, int line = __LINE__) { writeln( file, "(", line, "): ", __traits(identifier, a), " = ", a ); } int value = 10; dbg!value; // filename.d(12): value = 10
Feb 01 2019
On Saturday, 2 February 2019 at 00:06:58 UTC, Rubn wrote:void dbg(alias a)(string file = __FILE__, int line = __LINE__) { writeln( file, "(", line, "): ", __traits(identifier, a), " = ", a ); }Nice! I wasn't aware of `__traits(identifier, a)`. What role does it play here? Further, can we make this variadic with respect to `alias a`?
Feb 01 2019
On Saturday, 2 February 2019 at 00:25:02 UTC, Per Nordlöw wrote:I wasn't aware of `__traits(identifier, a)`. What role does it play here?Ahh, of course, I returns the symbol name as a `string`.
Feb 01 2019
On Saturday, 2 February 2019 at 00:25:02 UTC, Per Nordlöw wrote:On Saturday, 2 February 2019 at 00:06:58 UTC, Rubn wrote:I got this working without using the alias a, but working with variadic: ``` template dbg(args...) { alias dbgImpl!(args).print dbg; } template dbgImpl(args...) { void print(string file = __FILE__, uint line = __LINE__, string fun = __FUNCTION__) { static foreach (int i, a; args) { debug stderr.writefln("[%s:%s (%s)] %s = %s", file, line, fun, __traits(identifier, args[i]), args[i]); } } } void main() { int i; float f = 3.14; string s = "some string"; dbg!(i, f, s); } ``` prints: [dbg.d:28 (dbg.main)] i = 0 [dbg.d:28 (dbg.main)] f = 3.14 [dbg.d:28 (dbg.main)] s = some stringvoid dbg(alias a)(string file = __FILE__, int line = __LINE__) { writeln( file, "(", line, "): ", __traits(identifier, a), " = ", a ); }Nice! I wasn't aware of `__traits(identifier, a)`. What role does it play here? Further, can we make this variadic with respect to `alias a`?
Feb 01 2019
On Saturday, 2 February 2019 at 00:06:58 UTC, Rubn wrote:import std.stdio; void dbg(alias a)(string file = __FILE__, int line = __LINE__) { writeln( file, "(", line, "): ", __traits(identifier, a), " = ", a ); } int value = 10; dbg!value; // filename.d(12): value = 10I did think it was weird that a similar result couldn't be produced using __FILE__ and __LINE__, given that even C++ has them. Look like something that could be added to std.stdio. Only problem: dbg!(2 + 1); // Prints "a = 3" (could be mitigated by naming the alias "_")
Feb 02 2019
On Saturday, 2 February 2019 at 10:42:27 UTC, Olivier FAURE wrote:(could be mitigated by naming the alias "_")Or adding a new "expressionString" trait applicable to aliases and variadic templates. A trait like that might be useful for smart assertions.
Feb 02 2019
On Friday, 1 February 2019 at 15:49:24 UTC, Per Nordlöw wrote:Rust just added a standard macro `dbg` for debug printing https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#the-dbg-macro [...]What's wrong with `debug log(<whatever>);` from `std.experimental.logger;`? Works like a charm in my project. The message is prepended with a time stamp and location in file/function/line.
Feb 02 2019
On 2019-02-02 13:08, Patrick Schluter wrote:What's wrong with `debug log(<whatever>);` from `std.experimental.logger;`? Works like a charm in my project. The message is prepended with a time stamp and location in file/function/line.I think what's missing is the variable name not being automatically added to the message printed. -- /Jacob Carlborg
Feb 02 2019
On Saturday, 2 February 2019 at 12:08:02 UTC, Patrick Schluter wrote:On Friday, 1 February 2019 at 15:49:24 UTC, Per Nordlöw wrote:This! I think everyone here has forgotten about the debug keyword and compiler switch.Rust just added a standard macro `dbg` for debug printing https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#the-dbg-macro [...]What's wrong with `debug log(<whatever>);` from `std.experimental.logger;`? Works like a charm in my project. The message is prepended with a time stamp and location in file/function/line.
Feb 02 2019
On Friday, 1 February 2019 at 15:49:24 UTC, Per Nordlöw wrote:[...]Alright, after quite some work I finally managed to do the following code printing also nested variable names from classes & structs. I am not sure it's quite the same as the Rust AST macro for that, but I guess it's still interesting: import std.stdio; template dbg(args...) { alias dbgImpl!(args).print dbg; } template dbgImpl(args...) { import std.traits; void print(string file = __FILE__, uint line = __LINE__, string fun = __FUNCTION__) { static foreach (_; args) { static if(isBuiltinType!(typeof(_))) debug stderr.writefln("[%s:%s (%s)] %s = %s", file, line, fun, __traits(identifier, _), _); static if(isAggregateType!(typeof(_))) { debug stderr.writefln("[%s:%s (%s)] %s = %s", file, line, fun, __traits(identifier, _), toDbgString(_)); } } } string toDbgString(Arg)(Arg o) { string dbgstr = "("; import std.format; static foreach(f; FieldNameTuple!(typeof(o))) { static if(isBuiltinType!(typeof(__traits(getMember, o, f)))) { dbgstr ~= format("%s:%s, ", f, __traits(getMember, o, f)); } static if(isAggregateType!(typeof(__traits(getMember, o, f)))) { dbgstr ~= format("%s = %s, ", f, toDbgString(__traits(getMember, o, f))); } } return dbgstr[0..$-2] ~ ")"; } } struct Foo{ int s = 2; bool b = false; Bar bar;} struct Bar{ auto c = 'c';} class FooBar{ int t; Foo f; } void main() { int i; float f = 3.14; string s = "some string"; Foo foo; Bar bar; FooBar fb = new FooBar; dbg!(i, f, s, foo, 1+3, foo, bar, fb); // prints: // [dbg.d:54 (dbg.main)] i = 0 // [dbg.d:54 (dbg.main)] f = 3.14 // [dbg.d:54 (dbg.main)] s = some string // [dbg.d:54 (dbg.main)] foo = (s:2, b:false, bar = (c:c)) // [dbg.d:54 (dbg.main)] _ = 4 // [dbg.d:54 (dbg.main)] foo = (s:2, b:false, bar = (c:c)) // [dbg.d:54 (dbg.main)] bar = (c:c) // [dbg.d:54 (dbg.main)] fb = (t:0, f = (s:2, b:false, bar = (c:c))) }
Feb 02 2019
On Saturday, 2 February 2019 at 14:58:42 UTC, ezneh wrote:import std.stdio; template dbg(args...) { alias dbgImpl!(args).print dbg; ...Great! Close enough for me! Thanks!
Feb 03 2019
On 2019-02-02 14:58:42 +0000, ezneh said:On Friday, 1 February 2019 at 15:49:24 UTC, Per Nordlöw wrote:This looks great, but I get: Error: value of this is not known at compile time for the static foreach() line in dbgImpl. So, wondering what I'm doing wrong... -- Robert M. Münch http://www.saphirion.com smarter | better | faster[...]Alright, after quite some work I finally managed to do the following code printing also nested variable names from classes & structs. I am not sure it's quite the same as the Rust AST macro for that, but I guess it's still interesting: ...
Nov 17 2019