[Rd] puzzled by cat() behaviour when argument '...' is a vector (and argument 'sep' contains "\n")

William Dunlap wdunlap at tibco.com
Thu Nov 6 01:51:04 CET 2008


> From: r-devel-bounces at r-project.org
> [mailto:r-devel-bounces at r-project.org] On Behalf Of Duncan Murdoch
> Sent: Wednesday, November 05, 2008 3:53 PM
> To: Peter Ruckdeschel
> Cc: r-devel at r-project.org
> Subject: Re: [Rd] puzzled by cat() behaviour when argument
> '...' is a vector (and argument 'sep' contains "\n")
>
> On 05/11/2008 5:47 PM, Peter Ruckdeschel wrote:
> > Hi r-devels,
> >
> > I am a bit puzzled by the behaviour of  cat() --- any help
> is appreciated...
> >
> > At least AFAICS, cat() for vector-valued '...' argument behaves in
> > contradiction to what I understand from the note in the
> help to cat()
> > which reads
> >
> > "
> > Despite its name and earlier documentation, 'sep' is a vector of
> >      terminators rather than separators, being output after every
> >      vector element (including the last).  Entries are recycled as
> >      needed.
> > "
>
> I think you're right that the documentation is incorrect. 
> I'd prefer a patch to the docs, rather than a change to the
> behaviour:  cat() is so fundamental that any changes to it
> would have wide ranging consequences.
>
> If you want to study the code and draft a documentation
> patch, I'll review it and possibly commit it.
>
> Duncan Murdoch

For what it is worth, S+ and R differ in how a vector sep argument
is treated.  R uses the vector sep only if cat() is given a vector of
strings for the ... argument but S+ treats cat(c(...),sep=sep)
the same as cat(..., sep=sep).  E.g., the following cat(...,sep=sep)
uses all of sep in S+ but only sep[1] in R:
   > cat("One.", "Two words.", "Three more words.",
sep=c("<end1><start2>", "<end2>\n<start3>", "<end3>"))
   S+: One.<end1><start2>Two words.<end2>
   S+: <start3>Three more words.
   R : One.<end1><start2>Two words.<end1><start2>Three more words.
but the following cat(c(...),sep=sep) uses all of sep in both
   > cat(c("One.", "Two words.", "Three more words."),
sep=c("<end1><start2>", "<end2>\n<start3>", "<end3>"))
   S+: One.<end1><start2>Two words.<end2>
   S+: <start3>Three more words.
   R : One.<end1><start2>Two words.<end2>
   R : <start3>Three more words.
If there are several c(...) entries in cat() it gets more complicated.
E.g.,
   > cat(c("One.", "Two words.", "Three more words."), c("Fourth
entry.", "No. 5."),
          sep=c("<end1><start2>", "<end2>\n<start3>", "<end3>"))
   S+: One.<end1><start2>Two words.<end2>
   S+: <start3>Three more words.<end3>Fourth entry.<end1><start2>No. 5.
   R : One.<end1><start2>Two words.<end2>
   R : <start3>Three more words.<end1><start2>Fourth
entry.<end1><start2>No. 5.

In both, if any of the sep values include a newline, a newline is
appended
to the end of the cat() output.

Neither use any entry in sep after the end of the cat() output,
although,
because of the previous rule, it may seem that they do in the common
case
of sep="".

I had forgotten that sep= could be vectorized and use paste() instead of
cat() when I needed such functionality.  IMO, paste() has fewer
surprises.

Bill Dunlap
TIBCO Spotfire Inc
wdunlap tibco.com 



More information about the R-devel mailing list