55

cat and print both seem to offer a "print" functionality in R.

x <- 'Hello world!\n'
cat(x)
# Hello world!
print(x)
# [1] "Hello world!\n"

My impression is that cat most resembles the typical "print" function. When do I use cat, and when do I use print?

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
Simon Kuang
  • 3,870
  • 4
  • 27
  • 53
  • See here: https://stat.ethz.ch/pipermail/r-help/2004-September/056972.html –  Aug 05 '15 at 22:37
  • possible duplicate of [The difference between concatenating character strings with paste() vs. cat()?](http://stackoverflow.com/questions/12775085/the-difference-between-concatenating-character-strings-with-paste-vs-cat) – MichaelChirico Aug 05 '15 at 23:16

2 Answers2

50

cat is valid only for atomic types (logical, integer, real, complex, character) and names. It means you cannot call cat on a non-empty list or any type of object. In practice it simply converts arguments to characters and concatenates so you can think of something like as.character() %>% paste().

print is a generic function so you can define a specific implementation for a certain S3 class.

> foo <- "foo"
> print(foo)
[1] "foo"
> attributes(foo)$class <- "foo"
> print(foo)
[1] "foo"
attr(,"class")
[1] "foo"
> print.foo <- function(x) print("This is foo")
> print(foo)
[1] "This is foo"

Another difference between cat and print is returned value. cat invisibly returns NULL while print returns its argument. This property of print makes it particularly useful when combined with pipes:

coefs <- lm(Sepal.Width ~  Petal.Length, iris) %>%
         print() %>%
         coefficients()

Most of the time what you want is print. cat can useful for things like writing a string to file:

sink("foobar.txt")
cat('"foo"\n')
cat('"bar"')
sink()

As pointed by baptiste you can use cat to redirect output directly to file. So equivalent of the above would be something like this:

cat('"foo"', '"bar"', file="foobar.txt", sep="\n")

If you want to write lines incrementally you should use append argument:

cat('"foo"', file="foobar.txt", append=TRUE)
cat('"bar"', file="foobar.txt", append=TRUE)

Compared to sink approach it is far to verbose for my taste, but it is still an option.

Community
  • 1
  • 1
zero323
  • 322,348
  • 103
  • 959
  • 935
  • 1
    Also: `?cat` and `?print` – MichaelChirico Aug 05 '15 at 23:13
  • 3
    why would use sink(), when cat() has a file argument? – baptiste Aug 05 '15 at 23:22
  • 2
    @baptiste It has, but if you want to write multiple lines passing both `file` and `append=TRUE` is kind of tedious. – zero323 Aug 05 '15 at 23:25
  • @zero323 in that case you can open a connection for writing and leave it open until you're done. Also, there's no reason you couldn't use `print` with `sink`. – GSee Aug 06 '15 at 13:34
  • @GSee I've never said you cannot. Still, `cat` allows you to output exact string. I know you can use `print` with `quote=FALSE` to avoid string quote and embedded quote escaping but is there any way to avoid vector representation for a character of length 1? I mean no leading `[1]` for something like `print('"foo"', quote=FALSE).` – zero323 Aug 06 '15 at 13:55
14

An essential difference between cat and print is the class of the object they return. This difference has practical consequences for what you can do with the returned object.

print returns a character vector:

> print(paste("a", 100* 1:3))
[1] "a 100" "a 200" "a 300"

> class(print(paste("a", 100* 1:3)))
[1] "a 100" "a 200" "a 300"
[1] "character" 

cat returns an object of class NULL.

> cat(paste("a", 100* 1:3))
a 100 a 200 a 300

> class(cat(paste("a", 100* 1:3)))
a 100 a 200 a 300[1] "NULL"

In some cases, it is important to return the output as is in your console, for example when you want to copy-paste the output. In those cases, you really don't want to return a character vector. I found it a useful strategy in those cases to combine print and cat: Use print to create the object, use cat to print it to your console.

> output <- print(paste("a", 100* 1:3)) # use print to create the object
> cat(output) # use cat to print it *as is* to your console
a 100 a 200 a 300

Using xtable package for printing LaTeX tables in R:

> require(xtable)
> df <- data.frame(a = 1, č = 5) # dataframe with foreign characters
> output <- print(xtable(df), include.rownames = FALSE)
> output <- gsub("č", "c", output) # replace foreign characters before 
> # copying to LaTeX

> cat(output)
\begin{table}[ht]
\centering
\begin{tabular}{rr}
\hline
a & c \\
\hline
1.00 & 5.00 \\ 
\hline
\end{tabular}\end{table}

> print(output)
[1] "\\begin{table}[ht]\n\\centering\n\\begin{tabular}{rr}\n  
\hline\na & c    \\\\ \n  \\hline\n1.00 & 5.00 \\\\ \n   
\\hline\n\\end{tabular}\n\\end{table}\n"
Annerose N
  • 477
  • 6
  • 14
  • 3
    print (often) returns the value that was given in the input. Hence: class(print(1:3)) will return an integer. – Tal Galili Oct 30 '16 at 12:30