brodie gaslam
2020-May-10 15:13 UTC
[Rd] Minor Infelicity in Printing of Objects Nested in Lists
Currently S3 objects nested in generic vectors cause the tag buffer to be reset.? This feels sub-optimal for those objects that don't have a print method:> list(a=list(b='hello'))$a $a$b???????????????? ### <<<< notice "$a$b" [1] "hello"> list(a=structure(list(b='hello'), class='world'))$a $b?????????????????? ### <<<< notice "$b", not "$a$b" [1] "hello" attr(,"class") [1] "world" This happens because the default print method resets the tag buffer anytime it's called[1], whether by a custom print method, or by internal C code as part of the recursion into objects in `printValueRec`[2]. One possible way to "fix" this is to make it the responsibility of `printValueRec` to reset the tag buffer on exit from the top level, but that would mean always having an active context to catch errors instead of just for win32 as is the case now.? Additionally, print method authors may themselves intentionally rely on `print.default` for some parts their output, in which case it may be desirable to reset the tag buffer. Obviously not a big deal.? In my use case it can make it difficult to identify what part of a complex object caused a difference in a diff with a few neighboring context lines.? Just mentioning it in case there is interest in doing something about it.? If so I'll be happy to create a bugzilla ticket and assist with patches/testing. Best, B. [1]: https://github.com/wch/r-source/blob/tags/R-4-0-0/src/main/print.c#L309 [2]: https://github.com/wch/r-source/blob/tags/R-4-0-0/src/main/print.c#L570
Lionel Henry
2020-May-10 16:22 UTC
[Rd] Minor Infelicity in Printing of Objects Nested in Lists
Hello, The main reason for resetting the tagbuf in `print.default()` and other entry points to the print routine is that it is currently not reset on exit. Creating a context to reset it on exit to its last value might work. This should be done in the entry points rather than in print-value-rec though, since callers of the latter might write to the tagbuf. Another solution to this problem is proposed with the first patch in https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17610. Maybe I should extract this patch into its own entry so the discussion can be separate from the other patches. The idea is to pass the tag buffer as argument to the `print()` generic so it can be passed again to `print.default()`. The added benefit is that print methods can then pass their own tagbuf, which should be useful for printing special list-like objects. The downside is that it is technically a breaking change for methods that pass their dots to other functions (there's a couple of occurrences of this in the base packages). However I think such usage is not recommended for print methods because `print()` is a recursive generic that dispatches on heterogeneous objects. For example the user might pass `digits = 2` to print a list of objects. The print methods should make sure they ignore any unknown arguments. Best, Lionel On 5/10/20, brodie gaslam via R-devel <r-devel at r-project.org> wrote:> Currently S3 objects nested in generic vectors cause the tag buffer to be > reset.? This feels sub-optimal for those objects that don't have a print > method: > >> list(a=list(b='hello')) > $a > $a$b???????????????? ### <<<< notice "$a$b" > [1] "hello" > > >> list(a=structure(list(b='hello'), class='world')) > $a > $b?????????????????? ### <<<< notice "$b", not "$a$b" > [1] "hello" > > attr(,"class") > [1] "world" > > This happens because the default print method resets the tag buffer anytime > it's called[1], whether by a custom print method, or by internal C code as > part of the recursion into objects in `printValueRec`[2]. > > One possible way to "fix" this is to make it the responsibility of > `printValueRec` to reset the tag buffer on exit from the top level, but that > would mean always having an active context to catch errors instead of just > for win32 as is the case now.? Additionally, print method authors may > themselves intentionally rely on `print.default` for some parts their > output, in which case it may be desirable to reset the tag buffer. > > Obviously not a big deal.? In my use case it can make it difficult to > identify what part of a complex object caused a difference in a diff with a > few neighboring context lines.? Just mentioning it in case there is interest > in doing something about it.? If so I'll be happy to create a bugzilla > ticket and assist with patches/testing. > > Best, > > B. > > [1]: > https://github.com/wch/r-source/blob/tags/R-4-0-0/src/main/print.c#L309 > [2]: > https://github.com/wch/r-source/blob/tags/R-4-0-0/src/main/print.c#L570 > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >
brodie gaslam
2020-May-10 18:46 UTC
[Rd] Minor Infelicity in Printing of Objects Nested in Lists
> On Sunday, May 10, 2020, 12:24:17 PM EDT, Lionel Henry <lionel at rstudio.com> wrote: > > The main reason for resetting the tagbuf in `print.default()` and > other entry points to the print routine is that it is currently not > reset on exit. Creating a context to reset it on exit to its last > value might work. This should be done in the entry points rather than > in print-value-rec though, since callers of the latter might write to > the tagbuf. > > Another solution to this problem is proposed with the first patch in > https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17610. Maybe I > should extract this patch into its own entry so the discussion can be > separate from the other patches.Ah, looks like the exact same issue, at least the first patch.? I'm not wed to any particular solution, but I am happy to help test/work on this if there is interest in addressing this. Best, B.>On 5/10/20, brodie gaslam via R-devel <r-devel at r-project.org> wrote: >> Currently S3 objects nested in generic vectors cause the tag buffer to be >> reset.? This feels sub-optimal for those objects that don't have a print >> method: >> >>> list(a=list(b='hello')) >> $a >> $a$b???????????????? ### <<<< notice "$a$b" >> [1] "hello" >> >> >>> list(a=structure(list(b='hello'), class='world')) >> $a >> $b?????????????????? ### <<<< notice "$b", not "$a$b" >> [1] "hello" >> >> attr(,"class") >> [1] "world"