print/show of self-referential objects

97 views
Skip to first unread message

Kevin Squire

unread,
Aug 2, 2012, 1:25:52 AM8/2/12
to juli...@googlegroups.com
Hi all,

Right now, the default printing of self-referential objects enters an infinite loop:

julia> type SelfReferential
         obj::SelfReferential
         SelfReferential() = (x = new(); x.obj = x)
       end

julia> a = SelfReferential() 
SelfReferential(SelfReferential(SelfReferential(SelfReferential(SelfReferential...(<clip>)

Previously [1], Jeff stated that print() defaults to calling show(), but that doesn't seem to be true now:

julia> show(x::SelfReferential) = print("SelfReferential()")  

julia> show(a)
SelfReferential()
julia> print(a)
SelfReferential(SelfReferential(SelfReferential(SelfReferential(SelfReferential...(<clip>)

Is there another way to fix this, or should I file a bug?  (I'm using Version 0.0.0+92844055.rf453, from earlier today).

Jeff's post that I referred to above cleared things up a bit for me, but I'm still finding show/print somewhat confusing.  Python, which I'm most familiar with, has clear conventions (not strictly enforced, but generally followed): __repr__ is supposed to show an unambiguous Pythonic(-ish) representation of an object, and __str__ is supposed to be readable [2].  In Julia, does show==__str__ and print==__repr__?  E.g., I was looking at list.jl earlier, and while not the most canonical example, it seems to follow this somewhat:

julia> load("examples/list.jl")

julia> a = list(1,2,3)
Cons(1,Cons(2,Cons(3,Nil())))

julia> show(a)
list(1, 2, 3)
julia> print(a)
Cons(1,Cons(2,Cons(3,Nil())))

For most other things, though, print() and show() seem to be the same.  Can someone help clarify?

Thanks,

   Kevin

Keno Fischer

unread,
Aug 2, 2012, 4:00:17 AM8/2/12
to juli...@googlegroups.com
IIRC you have to define `show(stream,x::SelfReferential)=print(stream,"SelfReferential")`.

--
 
 
 

Jeff Bezanson

unread,
Aug 2, 2012, 12:41:50 PM8/2/12
to juli...@googlegroups.com
Yes, this is a tricky case where you always have to define
show(stream,x) or print(stream,x), but show(x) and print(x) are
provided for convenience. Ideally we'd prevent adding new
single-argument definitions, but that isn't our style.

We do not have a function that's supposed to print readable
representations. I acknowledge read and print as lisp's major
strengths, but outside of JSON people don't seem to favor
programming-language-based storage and interchange formats. show() is
for displaying pretty representations at the prompt, and print() is
for canonical text representations (e.g. unquoted strings), defaulting
to show() for values without canonical representations. Then you have
standard formats like CSV, or binary serialization for something
efficient and julia-specific. Although readable representations seem
ideal, after all these other options there is strangely little room
left for them.
> --
>
>
>

Kevin Squire

unread,
Aug 2, 2012, 2:10:20 PM8/2/12
to juli...@googlegroups.com
Thank you to both of you for the explanation and simple fix!

We do not have a function that's supposed to print readable
representations. I acknowledge read and print as lisp's major
strengths, but outside of JSON people don't seem to favor
programming-language-based storage and interchange formats. show() is
for displaying pretty representations at the prompt, and print() is
for canonical text representations (e.g. unquoted strings), defaulting
to show() for values without canonical representations. Then you have
standard formats like CSV, or binary serialization for something
efficient and julia-specific. Although readable representations seem
ideal, after all these other options there is strangely little room
left for them.

I see your point, although I'm missing that.  I've been working on a qsub() function that submits jobs to an SGE cluster.  I'm using julia as the shell(*) to run the commands on remote nodes so that I can use Pipelines and Cmds in a more flexible fashion than in shell.  Ideally, I'd like to generate pipelines on the local machine, and turn that into a script to feed to SGE to run on the remote machine, but doing so in a readable fashion has been challenging for anything beyond a simple Cmd().  I'll probably just end up creating strings instead of Cmds, since it's easier to turn strings into scripts of Cmds and Pipelines than to deconstruct a pipeline into a script.  There are other ways I could do this (e.g., start a remote julia process that reads a serialize Pipeline from a file or socket), but having a script around to debug when things go wrong is quite useful.  So a repr() command would be nice... but I concede that julia isn't lisp and most people don't really need this functionality.

Anyway, I've learned a bit about Cmds and Pipelines in julia while working on this, which has been fun.

Kevin


(*) Is it possible to have a reduced-memory-footprint julia shell for situations like this?  These processes won't be doing any matrix calculations directly.
Reply all
Reply to author
Forward
0 new messages