There are many ways one may want to register changes in data. That is why lumberjack
allows you to write your own loggers. Here, you can read how to do it.
A logger is a reference object wich must have the following methods:
$add(meta, input, output)
. This is a function that adds computes the difference between input
and output
and adds it to a log. The meta
argument is a list
with two elements:
expr
The expression used to turn input
into output
src
The same expression, but turned into a string.$dump()
This function writes dumps the current logging info somewhere. Often this will be a file, but it is completely flexible.There are several systems in R to build such reference object. We recommend using R6 classes or Reference classes.
Below we give an example in each system. The example loggers only register whether something has ever changed. A dump
results in a simple message on screen.
An introduction to R6 classes can be found here
Let us define the ‘trivial’ logger.
library(R6)
trivial <- R6Class("trivial",
public = list(
changed = NULL
, initialize = function(){
self$changed <- FALSE
}
, add = function(meta, input, output){
self$changed <- self$changed | !identical(input, output)
}
, dump = function(){
msg <- if(self$changed) "" else "not "
cat(sprintf("The data has %schanged\n",msg))
}
)
)
Here is how to use it.
library(lumberjack)
out <- women %>>%
start_log(trivial$new()) %>>%
identity() %>>%
dump_log(stop=TRUE)
## The data has not changed
out <- women %>>%
start_log(trivial$new()) %>>%
head() %>>%
dump_log(stop=TRUE)
## The data has changed
Reference classes (RC) come with the R recommended methods
package. An introduction can be found here. Here is how to define the trivial
logger as a reference class.
library(methods)
trivial <- setRefClass("trivial",
fields = list(
changed = "logical"
),
methods = list(
initialize = function(){
.self$changed = FALSE
}
, add = function(meta, input, output){
.self$changed <- .self$changed | !identical(input,output)
}
, dump = function(){
msg <- if( .self$changed ) "" else "not "
cat(sprintf("The data has %schanged\n",msg))
}
)
)
And here is how to use it.
library(lumberjack)
out <- women %>>%
start_log(trivial()) %>>%
identity() %>>%
dump_log(stop=TRUE)
## The data has not changed
out <- women %>>%
start_log(trivial()) %>>%
head() %>>%
dump_log(stop=TRUE)
## The data has changed
Observe that there are subtle differences between R6 and Reference classes (RC).
self
, in RC this is done with .self
.classname$new()
, an RC object is initialized with classname()
.