26 Side-effect functions should return invisibly

26.1 What’s the pattern?

If a function is called primarily for its side-effects, it should invisibly return a useful output. If there’s no obvious output, return the first argument. This makes it possible to use the function with in a pipeline.

26.2 What are some examples?

  • print(x) invisibly returns the printed object.

  • x <- y invisible returns y. This is what makes it possible to chain together multiple assignments x <- y <- z <- 1

  • readr::write_csv() invisibly returns the data frame that was saved.

  • purrr::walk() invisibly returns the vector iterated over.

  • fs:file_copy(from, to) returns to

  • options() and par() invisibly return the previous value so you can reset with on.exit().

26.3 Why is it important?

Invisibly returning the first argument allows to call the function mid-pipe for its side-effects while allow the primary data to continue flowing through the pipe. This is useful for generating intermediate diagnostics, or for saving multiple output formats.

Functions that modify some global state, like options() or par(), should return the previous value of the variables. This, in combination with Section 10.3.2, makes it possible to easily reset the effect of the change: