show, print, write, etc.

92 views
Skip to first unread message

Harlan Harris

unread,
May 6, 2012, 9:04:21 PM5/6/12
to juli...@googlegroups.com
Specifically for Jeff, I think...

I see that you changed a bunch of stuff related to show, string, sshow, print, and write methods recently. Can I just clarify what we're supposed to define for, say, new types?

Between the manual and the code, I infer the following:

show(io, x) should be defined for any user-visible type.
print(io, x) need not be defined, but if it is, it should be simpler than show. (What's an example of when this distinction is needed?)
showall(io, x) may be defined if show(x) would normally truncate output, as in large arrays.
dump(io, x) may be defined, and if so, it should show details that other methods don't.

string(x) shouldn't be defined manually -- it's based on show(x) by default. (although your check-in note suggests it's based on print?)

sshow(x) is somehow district from string(x), but I don't understand how.

write(io, x) shouldn't generally be defined for new types? or should it?

Thanks,

 -Harlan



Jeff Bezanson

unread,
May 7, 2012, 2:54:57 AM5/7/12
to juli...@googlegroups.com
Yes, show(io, x) is the the basic thing that should be defined.
print() defaults to calling show.

print() is only different for objects with a canonical text
representation: strings and characters.

dump() isn't really meant to be overloaded; the idea is to spill
everything about an object's state in some universal way.

string() print()s its arguments to a string. This is so
string(Char,Char) and string(String) do what you'd expect.

sshow() show()s its arguments to a string. This is only needed if you
want strings to come out quoted, etc.

write(io, x) writes canonical binary representations, like the 4 bytes
in an Int32. It certainly makes sense to define for new types; a good
example is SubArray, which writes the elements it references without
copying them out first.

Vitalie Spinu

unread,
May 7, 2012, 4:52:29 AM5/7/12
to juli...@googlegroups.com

May I suggest adding "str" or "struct", to print very concise (one line
per field) representation of an object. It is called recursively on
inner components in hierarchical structures.

By far my most used function in an interactive R session:

> str(iris)
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

> tl <- list(a=34,b=list(c=3,d=4), e="sfddsf")
> str(tl)
List of 3
$ a: num 34
$ b:List of 2
..$ c: num 3
..$ d: num 4
$ e: chr "sfddsf"



>>>> Jeff Bezanson <jeff.b...@gmail.com>

Harlan Harris

unread,
May 7, 2012, 7:24:23 AM5/7/12
to juli...@googlegroups.com
Thanks Jeff! Makes sense now!

Vitalie, good idea. In my prototype DataFrame code, I've implemented exactly that. But does it make sense to define it in general? Or just for statistical data structures? It only works for R because everything is a named list...

 -Harlan

Vitalie Spinu

unread,
May 7, 2012, 8:20:01 AM5/7/12
to juli...@googlegroups.com

>>>> Harlan Harris <har...@harris.name>
>>>> on Mon, 7 May 2012 07:24:23 -0400 wrote:

> Vitalie, good idea. In my prototype DataFrame code, I've implemented
> exactly that. But does it make sense to define it in general? Or just for
> statistical data structures? It only works for R because everything is a
> named list...

The main thing is to be able to see at a glance the internal structure
of an object.

It especially makes sense when objects are constructed
hierarchically. What is hierarchy, of course, depends on the
type. Fields in composite types, or elements of cell arrays are examples
of sub-structures.

Vitalie.

Harlan Harris

unread,
May 7, 2012, 8:42:11 AM5/7/12
to juli...@googlegroups.com
On Mon, May 7, 2012 at 8:20 AM, Vitalie Spinu <spin...@gmail.com> wrote:
 > Vitalie, good idea. In my prototype DataFrame code, I've implemented
 > exactly that. But does it make sense to define it in general? Or just for
 > statistical data structures? It only works for R because everything is a
 > named list...

The main thing is to be able to see at a glance the internal structure
of an object.

It especially makes sense when objects are constructed
hierarchically. What is hierarchy, of course, depends on the
type. Fields in composite types, or elements of cell arrays are examples
of sub-structures.

Yes, but in R it works because R has reflection, so you can get the name of every field in a composite object by a lookup at runtime. Julia doesn't (unless I missed something), so the only way to make str(x) work would be to define a str(x::T) method for every type. Doesn't sound realistic... (unless I missed something...)

 -Harlan

Tim Holy

unread,
May 7, 2012, 8:56:17 AM5/7/12
to juli...@googlegroups.com
On Monday, May 07, 2012 08:42:11 AM Harlan Harris wrote:
> Yes, but in R it works because R has reflection, so you can get the name of
> every field in a composite object by a lookup at runtime. Julia doesn't

Try "names", e.g.,

julia> Range{Int}.names
(start,step,len)

--Tim

Harlan Harris

unread,
May 7, 2012, 9:05:58 AM5/7/12
to juli...@googlegroups.com

Oh, not documented! I see. Yes, dump() in show.jl demonstrates how to use it. Yes, it would be relatively straightforward to write str(), then!

The base method would be str(io, x, n, indent), which would recursively dive into CompositeKind objects, decrementing n and incrementing indent, until n was 0.

 -Harlan

Vitalie Spinu

unread,
May 7, 2012, 9:29:29 AM5/7/12
to juli...@googlegroups.com
>>>> Harlan Harris <har...@harris.name>
I don't know how it works in Julia, but I suspect there should exist a
retrievable class representation object -- a meta information about each
composite type, inheritance, fields etc.

I think it would be good to base str() on that, and make it output short
class info as well.

Stefan Karpinski

unread,
May 7, 2012, 1:44:21 PM5/7/12
to juli...@googlegroups.com
Calling it str seems extremely confusing. What you're talking about is precisely the intent of dump. It needs some work, but how about fixing up dump so that it does what you want?

Vitalie Spinu

unread,
May 7, 2012, 2:01:17 PM5/7/12
to juli...@googlegroups.com

Nope, it's not the same; "str" gives an abbreviated version of an
object. It's aim is to show the structure, and not to dump the whole
internal representation. One line per object is the main principle. For
example vectors and arrays are abbreviated to first 4 elements.

Dump, the way I understand it, is supposed to be a human readable
representation of an object which could be read backwards by
Julia. (this is exactly what dump in R does, would be good to have same
names). Write() is also different, it writes binary representation.

I agree that "str" is a bit awkward in light of Julia's string naming
conventions. But this function, given how frequently it is used, should
be short and easy to type. Longer than 3 characters is too long.

>>>> Stefan Karpinski <stefan.k...@gmail.com>
Reply all
Reply to author
Forward
0 new messages