knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" ) demo_file <- file.path(tempdir(TRUE), "demo.R") demo_fns <- "# demo.R f1 <- function(x) { ic() if (x > 0) { f2() } } f2 <- function() { ic() } f3 <- function(x) { ic(x) } " cat(demo_fns, file = demo_file) source(demo_file)
icecream is designed to make print debugging easier. It allows you to print out an expression, its value and (optionally) which function and file the call originated in.
This is an R port of gruns/icecream. All credit for the idea belongs to Ansgar Grunseid.
Install from CRAN with:
install.packages("icecream")
Or you can install the development version from GitHub with:
devtools::install_github("lewinfox/icecream")
The ic()
function prints its argument and its value. It also returns the value of the evaluated
argument, meaning that it is effectively transparent in code - just wrap an expression in ic()
to
get debugging output.
library(icecream) is_negative <- function(x) x < 0 ic(is_negative(1)) ic(is_negative(-1))
You're more likely to want to do this within a function:
some_function <- function(x) { intermediate_value <- x * 10 answer <- ic(intermediate_value / 2) return(answer) } some_function(1) some_function(10)
More complex inputs like lists and data frames are summarised to avoid cluttering the terminal.
df <- ic(iris) my_list <- ic(list(a = 1, b = 3, c = 1:100))
Calling ic()
with no arguments causes it to print out the file, line and parent function it was
called from.
In this example we have a file demo.R
that contains two functions. We've inserted ic()
calls at
strategic points so we can track what's being executed.
source("demo.R") f1(-1) #> ℹ ic| `global::f1()` in demo.R:3:2 f1(1) #> ℹ ic| `global::f1()` in demo.R:3:2 #> ℹ ic| `global::f2()` in demo.R:10:2
In the case of functions that haven't been source()
d or loaded from a package there is no source
code to refer to. In these cases the function's environment will be displayed.
orphan_func <- function() { ic() TRUE } orphan_func() #> ℹ ic| `global::orphan_func()` in <env: global> #> [1] TRUE e <- new.env() attr(e, "name") <- "icecream_van" environment(orphan_func) <- e orphan_func() #> ℹ ic| `orphan_func()` in <env: icecream_van> #> [1] TRUE
The ic_enable()
and ic_disable()
functions enable or disable the ic()
function. If disabled,
ic()
will return the result of evaluating its input but will not print anything.
ic_enable() # This is TRUE by default ic(mean(1:100)) ic_disable() ic(mean(1:100))
ic_enable()
Convenience functions with_ic_enable()
and with_ic_disable()
are also provided.
ic_enable() with_ic_disable(ic(mean(1:100))) ic_disable() with_ic_enable(ic(mean(1:100)))
ic_enable()
The following options can be used to control behaviour:
icecream.enabled
Boolean. If FALSE
, calls to ic(foo)
simply evaluate and return foo
. No output is printed. This
option can be set directly or with the ic_enable()
and ic_disable()
functions.
icecream.prefix
This is printed at the beginning of every line. Defaults to "ic|"
.
old.prefix <- getOption("icecream.prefix")
ic(mean(1:5)) options(icecream.prefix = "DEBUG:") ic(mean(1:5)) options(icecream.prefix = "\U1F366") ic(mean(1:5))
options(icecream.prefix = old.prefix)
icecream.always.include.context
Boolean. If TRUE
, when calling ic(foo)
the source file and line will be printed along with the
expression and value. If no srcref()
is available the function's environment will be displayed
instead. This can be useful for more complicated debugging but produces a lot of output so is
disabled by default.
old.ctx <- getOption("icecream.always.include.context")
f3(1) #> ℹ ic| `x`: num 1 options(icecream.always.include.context = TRUE) f3(1) #> ℹ ic| `global::f3()` in demo.R:14:2 | `x`: num 1
When ic()
is called with no arguments, the context is always printed because showing the location
of the call is the only reason to call ic()
on its own.
options(icecream.always.include.context = old.ctx)
icecream.peeking.function
and icecream.max.lines
These two options control how the result of evaluation of an expression is printed. icecream.peeking.function
indicates the function that summarizes the object. Default value is ic_autopeek
, which works like utils::str
for most of the time, but gives more informative output
for lists
, data.frames
and their subclasses in a more compact way. icecream.max.lines
determines maximum number of lines that the peek of an object occupies; defaults to 1.
For more complex data you may want to use e.g. head
function and 5 lines.
old.fun <- getOption("icecream.peeking.function") old.lines <- getOption("icecream.max.lines")
data(iris) ic(iris) # we would like to see header of the data options(icecream.peeking.function = head, icecream.max.lines = 5) ic(iris)
options(icecream.peeking.function = old.fun, icecream.max.lines = old.lines)
Note that if icecream.max.lines
is greater than 1 and summary of an object is longer than 1, the
alert occupies one line more due to the header.
icecream.output.function
, icecream.arg.to.string.function
Not implemented yet. See the configuration section of the original project docs for details of what they will do.
ic.format()
(see here).ic.output.function
. At the moment it uses cli::cli_alert_info()
ic.arg.to.string.function
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.