www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9326] New: writeln to simply show pointed data

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326

           Summary: writeln to simply show pointed data
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc



A small demo program:


import std.stdio: writeln;
struct Foo {
    int x;
}
struct Node {
    Node* next;
}
void main() {
    Foo f = Foo(1);
    writeln("Simple struct: ", f);
    Foo* pf = new Foo(2);
    writeln("Struct from pointer: ", pf);
    Node* ptr = new Node(new Node(null));
    writeln("Singly linked list: ", ptr);
    Node* n1 = new Node(null);
    Node* n2 = new Node(n1);
    n1.next = n2;
    writeln("Circular singly linked list: ", n1);
}


Currently prints (dmd 2.062alpha):

Simple struct: Foo(1)
Struct from pointer: 1601F90
Singly linked list: 19C1F80
Circular singly linked list: 1601F60


For debugging, or just during the writing of code, I'd often like to see what's
pointed by those pointers.

So I suggest to enhance Phobos textual formatting a little, to produce
something simple like (on 64 bit pointers are longer):

Simple struct: Foo(1)
Struct from pointer: <1601F90*>Foo(2)
Singly linked list: <1601F80*>Node(<19C1F70*>Node(null))
Circular singly linked list: <1551F60*>Node(<1551F50*>Node(<1551F60*>...))


Notes:
- Numbers like 1551F50 are the pointer values in hex;
- The "*" helps remember that they are deferenced;
- The <> of <1551F50*> help better tell apart the pointer from the pointed
data.
- The ellipsis ... in Node(<1551F60*>...) means that this call to writeln has
already shown what this pointer points to.

- - - - - - - - - - - - - -

This change in textual formatting is not meant to influence the result of "%x",
just "%s":


import std.stdio: writefln;
struct Foo {
    int x;
}
void main() {
    Foo* pf = new Foo(100);
    writefln("%s", pf);
    writefln("%x", pf);
}


Currently prints:

1981F90
1981f90



After that improvement it should print something like:

<1581F90*>Foo(100)
1581f90

- - - - - - - - - - - - - -

To keep things simple it's better to not follow untyped pointers (void*):


import std.stdio: writefln;
struct Foo {
    int x;
}
void main() {
    Foo* pf = new Foo(100);
    void* ptr = cast(void*)pf;
    writefln("%s", pf);
}


It should print just:

1571F90

Or maybe something similar to:

<1581F90*>void

- - - - - - - - - - - - - -

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 16 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326


Dmitry Olshansky <dmitry.olsh gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dmitry.olsh gmail.com



02:53:08 PST ---


I don't think that stuffing various debugging trickery into writeln is a good
idea.

What about a dedicated primitive that may (by default!) use more convenient
formating fot this purpose?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 16 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326






Thank you for your comment.

 I don't think that stuffing various debugging trickery into writeln is a good
 idea.
I keep hearing similar comments since few years ago I asked for a better printing of associative arrays and arrays in D. But once you give D programmers such better printing (thanks to Hara work), they seem happy and unwilling to go back to a more limited printing. It's not a trick, showing what a pointer points to is printing of a basic built-in data structure of the language. Probably I got spoiled by modern dynamic languages, that being often used on the REPL, enjoy having good default printing. If you think this enhancement request is not a good idea, you must explain why. I have explained why it's a handy thing to have. (The implementation of this feature requires the formatting function to keep a set of already seen pointers. For simplicity I think a built-in associative array of void* is enough).
 What about a dedicated primitive that may (by default!) use more convenient
 formating fot this purpose?
Once the improved format() is implemented in Phobos, what's the point of artificially restricting the usefulness of writeln()? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326




Beside dynamic arrays, associative arrays and enums, D writeln is able to print
lazy ranges, so writeln is already rather capable:


import std.stdio, std.range;
void main() {
    writeln(iota(6));
}


Shows:

[0, 1, 2, 3, 4, 5]

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 16 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326




04:57:33 PST ---


 
 Thank you for your comment.
 
 I don't think that stuffing various debugging trickery into writeln is a good
 idea.
I keep hearing similar comments since few years ago I asked for a better printing of associative arrays and arrays in D. But once you give D programmers such better printing (thanks to Hara work), they seem happy and unwilling to go back to a more limited printing.
What Kenji did was a better printing for ranges in general that is far more powerful (and better integrated) then arrays.
 
 It's not a trick, showing what a pointer points to is printing of a basic
 built-in data structure of the language.
 
 Probably I got spoiled by modern dynamic languages, that being often used on
 the REPL, enjoy having good default printing.
 
 If you think this enhancement request is not a good idea, you must explain why.
 I have explained why it's a handy thing to have.
 
 (The implementation of this feature requires the formatting function to keep a
 set of already seen pointers. For simplicity I think a built-in associative
 array of void* is enough).
 
It's good that you answered it already: not everybody needs it yet it requires more complex code to be pulled in for everybody. Dynamic languages doesn't ever consider cost-to-benefit ratio it seems. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326




05:11:45 PST ---

 If you think this enhancement request is not a good idea, you must explain why.
 I have explained why it's a handy thing to have.
 
 (The implementation of this feature requires the formatting function to keep a
 set of already seen pointers. For simplicity I think a built-in associative
 array of void* is enough).
 
BTW if writeln starts allocating GC memory like that we'll have a revolt among users. The special case of debugging output doesn't look good enough to compromise the basic "no garabage involved" guarantee. Plus debug prints inside of a finalizer risk killing a program with current GC. This situation with GC should/might improve in the future though but it's just another problem to be aware of. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326






 BTW if writeln starts allocating GC memory like that we'll have a revolt among
 users. The special case of debugging output doesn't look good enough to
 compromise the basic "no garabage involved" guarantee.

 Plus debug prints inside of a finalizer risk killing a program with current GC.
 This situation with GC should/might improve in the future though but it's just
 another problem to be aware of.
Thank you for the answer. I didn't know writeln has strictly zero allocations. To detect clycles this enhancement needs some kind of set of untyped pointers. Such pointers never get deferenced and they must not used by the GC to keep data alive (so they are weak pointers). So such pointers are essentially of type uintptr_t (unsigned integral type large enough to hold a pointer). Such set of uintptr_t is allocated by the writeln, and it stops being useful when writeln ends (so it's possible to deallocate it). So maybe if necessary it's possible to allocate such memory from the C heap, and avoid that problem with the finalizer. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9326






 What Kenji did was a better printing for ranges in general that is far more
 powerful (and better integrated) then arrays.
Kenji (with help from others) has done many things on the writeln, like improving string printing, improving array printing, significantly improving associative array printing (maybe introducing xformat too). And I think he has added the printing for lazy ranges. He has also improved or added the printing of struct literals, improved the output in presence of const/immutable, improved the function literals, and other important details.
 It's good that you answered it already: not everybody needs it yet it requires
 more complex code to be pulled in for everybody. 
That's mostly true for every improvement listed above. There is also printf/puts.
 Dynamic languages doesn't ever consider cost-to-benefit ratio it seems.
considering how much common they are (and they are becoming) it seems a good deal. (But they usually don't have chains of raw pointers). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2013