Nate Thompson
Nate Thompson

Reputation: 635

R Function - Print When Not Assigned

I see there is another related question, but the answer isnt what I am looking for. I want a function that can be assigned to an object, but still will print the output even when assigned, but not double print it.

In this case:

fun <- function(x) {
print(x+1)
x+1
}
a <- fun(3)

In this case, it would both save to a, and it would print to console, which is what I want.

But in this case:

fun(3)

It would print to the console twice. Is there a way to get the desired result from case 1, without double printing on case 2?

Upvotes: 4

Views: 696

Answers (3)

Gregor Thomas
Gregor Thomas

Reputation: 145785

R functions shouldn't have unasked for "side effects". This isn't a rule, but a strong recommendation. As evidence for it being good practice, there are plenty of questions on SO like this one where a poorly behaved function prints output using print or cat that the end user struggles to disable.

Based on this, I would strongly encourage you to either use message() rather than print() or to add an argument that can disable the printing. message() is the "right" way print to the console during execution, but it won't format the result nicely depending on the data structure.

Thus, if your function expects simple outputs then I would recommend doing it like this:

fun <- function(x) {
  result = x + 1
  message(result)
  invisible(result)
}

If it might have more complicated output, you could try something like this (demoing on mtcars):

fun <- function(x) {
  result = head(mtcars)
  sapply(capture.output(print(result)), message)
  invisible(result)
}

Messages can easily be suppressed by wrapping the call in suppressMessages(), and message = F is a handy argument for knitr code chunks to say "ignore the messages".


The other option is to add an argument

fun <- function(x, quietly = FALSE) {
  result = x + 1
  if (!quietly) print(result)
  invisible(result)
}

And I'd also think long and hard about whether this strange behavior is really necessary. Usually, having functions that behave as expected is better than having special cases that throw expectations.

Upvotes: 1

Benjamin
Benjamin

Reputation: 17279

You can accomplish this same behavior with any function in R that visibly returns an object by wrapping it in parentheses.

fun <- function(x) {
  x+1
}

> (fun(3))
[1] 4

> (a = fun(3))
[1] 4

> a
[1] 4

Or, equivalently, you may simply call print on your assignment.

> print(fun(3))
[1] 4

I'm not sure rolling this functionality into a function has any benefits over using the existing print method outside of a function.

Upvotes: 1

Boudewijn Aasman
Boudewijn Aasman

Reputation: 1256

Assuming that you still want your function to return the 'x+1' value, you could just wrap it in the invisible function:

fun <- function(x) {
  print(x+1)
  invisible(x+1)
}

> fun(3)
[1] 4

> a = fun(3)
[1] 4

> a
[1] 4

This will only print it out once, while still retaining the 'x+1' value.

Upvotes: 5

Related Questions