Callback_r_and_basic_html_css_notes

2013-07-31 by

R and Callback functions + Some HTML/CSS formatting

A general explanation of what a callback function is can be found on stackoverflow. In these notes, we will try to explain how to create them, and use them in R. These notes are the summaries of Duncan Temple Lang's note. It leaves out all the stuff which i didn't understand, and some of the terminology might be wrong. simply due to my ignorance. This also focus on R-callback functions created and invoked from R.


Intro

The basic idea here is that we want to allow R functions to be automatically invoked at the end of each top-level expression. This might be usefull if one, for example, wants to have a call to save.image() periodically invoked to reduce the potential for data loss if a crash were to occur subsequently. Rather than being based on time and the current semantics of the event loop, it makes more sense to call save.image() at the end of a top-level task.

There are two basic functions with which one can add and remove R functions which are to be used as task callbacks that are to be invoked at the end of each top-level expression evaluation. These are addTaskCallback() for registering a handler, and removeTaskCallback() for removing one. Each function that is used as a task callback must accept at least four arguments.

Example of defining a callback function

counter <- function() {
    ctr <- 0
    function(expr, value, ok, visible) {
        ctr <<- ctr + 1
        cat("Count", ctr, "\n")
        TRUE
    }
}

The above example, is an example of a Closure. Closures provide a convenient way to create a function that has access to any additional data that it needs. That example, keeps tranck of a count of the number of times the callback has been invoked.

we can registers that R function to be called each time a top-level task is completed, by using addTaskCallback(), as follows:

addTaskCallback(counter())

Sometime, it is more convenient to not use closures but to have R call the function with an additional argument that gives additional context. In these cases, we can supply a value for the data argument of addTaskCallback() function. This object is stored by the callback mechanism and is given as a fifth argument to the callback when it is invoked. We will see an exmple of that later.

Return value of a Callback

The return value has special significance. It must be a single logical value.

  • If the function returns TRUE(), the callback is maintained in the list of callbacks and it will be invoked after the next task is completed.
  • If the function returns FALSE(), then the callback is removed from the list and won’t be called again by this mechanism.

Registering Multiple Handlers - the proper way!

The function taskCallbackManager() is a function that can be used to create a manager which handles other callbacks. The functions allow one to add() and remove() functions to and from a list of callbacks. When a top-level task is completed, the managers central callback (evaluate()) is called by the C-level mechanism and this, in turn, evaluates each of the callbacks it manages. In the next section, we will take a look at some examples, which will hopefully make things a bit clearer and easier.

Examples

The following is a simple example of how things work. The example handlers are not particularly interesting. But they illustrate how one can do different types of computations.

Example 2:

We continue our example by defining a times() function which will print a simple string to identify itself each time it is called.

times <- function(total = 3, name = "a") {
    ctr <- 1
    function(expr, val, ok, visible) {
        cat("[Task ", name, "] ", ctr, "\n", sep = "")
        ctr <<- ctr + 1
        return(ctr <= total)
    }
}

Note that this function is that it removes itself from the handler list after it has been called a particular number of time, because the condition in the return will evalues to FALSE when the ctr is larger than total

Example 3:

A third example is periodic(), that will be called after each top-level task, but only does something every period calls. The function in this example takes an additional argument - cmd - that is the value we give when registering the callback. In this case, we will pass an expression and periodic() will evaluate it.

periodic <- function(period = 4, ctr = 0) {
# period - the number of calls between performing the action.
# ctr - can be specified to start at a different point.
    function(expr, value, ok, visible, cmd) {
        ctr <<- (ctr + 1) %% period # %% is the remainder operator
        if(ctr == 0) eval(cmd)
        return(TRUE)
        }
    }

Usage Examples

NOTE: Results of the following examples, were NOT produced naturally using knitr. Instead the output was produced by cutting and pasting the code into from a regular R-session. The material that was copied back into this document is displayed in green.

Now that we have defined times and periodic we will show how they can be used, using addTaskCallback() or the more complex way using taskCallbackManager(); and what they produce when invoked in R


We first start by adding a collection of times() handlers. We given them different expiration numbers: 3, 4, 5, and 6. Also, we identify them as a, b, c, d. For the purpose of illustration, we ensure that none-are activated until we have registered them all. We do this by initially suspending the manager and then adding the tasks. Then we activate it again.

# example of using taskCallbackManager() to register a collection of handlers
h <- taskCallbackManager()
h$suspend()
h$add(times())
## [1] "1"
h$add(times(4,"b"))
## [1] "2"
h$add(times(5,"c"))
## [1] "3"
h$add(times(6,"d"))
## [1] "4"
h$suspend(FALSE)
## [Task a] 1
## [Task b] 1
## [Task c] 1
## [Task d] 1

The output below the suspend(FALSE) is from each of the handlers giving their counts and identifiers.

Next, we add a periodic() handler. We specify user data that R will pass to this function when it calls it. This is an expression that the handler function (i.e. the function returned by calling periodic()) will evaluate every 4th call.

addTaskCallback(periodic(), quote(print("ok")), name = "book3")
## book3 
##     2
## [Task a] 2
## [Task b] 2
## [Task c] 2
## [Task d] 2

Again, the output below the result is from the handlers. The most recently added handler in this call (the function returned from calling periodic()) does not generate any output. Note that after defining the function periodic(), the ctr has value of 1. So we must wait another 3 calls for it to perform its real action.

We can continue to give regular R commands and see how the handlers work. We issue arbitrary commands and look at the output from the handlers.

sum(rnorm(10))
## [1] -5.718
## [Task a] 3
## [Task b] 3
## [Task c] 3
## [Task d] 3

At this point, the first timer (a) - 1st callback/handler- has expired having reached its maximal count of 3. It has been removed from the list and so will not appear in any subsequent output. we continue with issuing R-command

sqrt(9)
## [1] 3
## [Task b] 4
## [Task c] 4
## [Task d] 4

At this point, handler ‘b’ - 2nd callback/handler- has also expired and is removed.

length(objects())
## [1] 3
## [Task c] 5
## [Task d] 5
## [1] "ok"

After the last command, Handler ‘c’ has expired. Also, since this is the 4-th call, the periodic() handler kicks in and evaluates its cmd argument. This is the expression print("ok") and gives rise to the last line of the output. Now the ctr variable in the periodic() function has been reset to 0, and so we must wait 4 calls for it to perform its action again.

Finally, when we keep on typing the following 4 commands

gamma(4)
## [1] 6
## [Task d] 6
gamma(4)
## [1] 6
gamma(4)
## [1] 6
gamma(4)
## [1] 6
## [1] "ok"

After the first of these calls, handler ‘d’ expires. The periodic() handler is still active. After the 4-th of these calls, it generates more output. And this will continue ad infinitum.

Removing Handlers

Removing handlers is quite simple. We can use either position indices or names. Names are preferred since positions change when other callbacks are removed.

removeTaskCallback("book3")
## [1] TRUE

Notes that were usefull when writting this document

  1. To underlying a text, we wrapped the text with the underline HTML tag, as follows: < u > text < /u > (without the spaces: right after the < , and right before the > brackets)

  2. To link a part of this document to another, we added anchar tags as described in this document. The following is an example: < a href="#myReference" > wordToBeClicked < /a >; and then later on where we want the link to directed to, we add < a name="myReference">< /a >. (without the spaces: right after the < , and right before the > brackets)

  3. To Color a specific part of a text, we wrapped the text as follow: < span style="color:#4C886B" >text< /span > (without the spaces: right after the < , and right before the > brackets)

  4. To convert from rgb color to Hexidecimal color code, I have used the converter on this site. Color:#4C886B is the green color used for the comments.

Thanks to Yinui Xie, creator of knitr package, who advised on the first 2 notes above, and on knitr limitation. He also brought to my attention that the giant behind markdown is HTML, and so I can include HTML tags directly in any RMarkdown and Knitr will take care of the rest.

Closures_notes

2013-07-13 by

Notes and Examples of Closures and Inheritance

Function have their own enviroments, and according to the this link a Closure is a function that is packaged with some state. The previous link is a good post for understanding Enviroments in R, but that is not the focus of these notes.

Another point to keep in mind before looking into Closures, is that according to R Language Definition, Functions (or more precisely, function closures) have three basic components: a formal argument list, a body and an environment.

So before getting lost into the details, in R, functions, enviroments and closures are all related concept, we hope in these notes, we illustrate how to create, use closure instead of giving an excat defintions.

Creating a closure according to Jeffrey A. Ryan

To create closures, we use the environment object in R. This allows for data and methods to reside within the object instances, making self-aware behavior and selective inheritence easy.

Creating a stack in R

  • A stack implementation consists of three main components:
    1. a container variable --- a.k.a. the stack (.Data)
    2. a push method to add elements (push)
    3. a pop method to remove elements (pop)

We will provide the full R implementation, in what what follows first, and then explain code. For step-by-step explanation, see original post.

# 1. Creating a new enviroment
stack <- new.env()
# 2. Creating a Data container (.Data) which is a vector which will contains our data, and which lives in the enviroment stack
stack$.Data <- vector()
# 3. Creating push method that acts on .Data. Note we use the << assignement operator
stack$push <- function(x) .Data <<- c(.Data, x)
# 4. Creating a pop method that acts on .Data
stack$pop <- function() {
    tmp <- .Data[length(.Data)]
    .Data <<- .Data[-length(.Data)]
    return(tmp)
}
# 5. Setting the enviroment of the push method to be the same as the enviroment of the stack object
environment(stack$push) <- as.environment(stack)
# 6. Setting the enviroment of the pop method to the same as the enviroment of the stack object
environment(stack$pop) <- as.environment(stack)
# 7. Setting the class attribute of our stack object to be 'stack' - this is not neccessarly step, but it will be needed later
class(stack) <- "stack"

The comments in the above code gives an step-by-step description on how to create a closure. However it's worth nothing that * If Step 5 and 6, were not included, then when we would have gotten an error when after step 4, we issue the following command.

stack$push(1)

the error that we would have gotten is object '.Data' not found, and that is because we haven't matched the environment of the function to the object's environment. R isn't starting its search for .Data in the correct location. That is why step 5 and 6 and needed and we used the function environment and as.environment.

Next, we are going to use S3 classes to create push and pop methods to make the calls look more like normal R. That is why step 7 above was needed. See Notes on S3 classes for further explanations

push <- function(x, value, ...) UseMethod("push")
pop <- function(x, ...) UseMethod("pop")
push.stack <- function(x, value, ...) x$push(value)
pop.stack <- function(x) x$pop()

Finally, in order to make the creation of the above code easier, we will wrap it in a function, so that we can create a closure with one 1 line instead of going through these 7 steps every time. The final code will look as follow

# This new_stack() becomes the constructor of the object whose class is 'stack'. Everything else in the code is the same as before
new_stack <- function() {
    stack <- new.env()
    stack$.Data <- vector()
    stack$push <- function(x) .Data <<- c(.Data, x)
    stack$pop <- function() {
        tmp <- .Data[length(.Data)]
        .Data <<- .Data[-length(.Data)]
        return(tmp)
    }
    environment(stack$push) <- as.environment(stack)
    environment(stack$pop) <- as.environment(stack)
    class(stack) <- "stack"
    stack
}

A Simpler Example.

The following examples was taken from taken here and uses functions to create a closure. This example does not uses enviroment since the data lives inside the function and not at the same level as the functions.

account <- function(balance = 0) {
    function(d = 0, w = 0) {
        newbal <- balance + d - w
        balance <<- newbal
        newbal
    }
}

In the above example, d stands for deposit, and w stands for withdrawl. This is a function of function, that it, when we assigned it to a variable, that variable is a function as we will see next. In the following instanciation, we will create an account for John and the initial balance of this account will be 100.

John <- account(100)

As we can see from the next statement, John is a function

John
## function(d = 0, w = 0) {
##         newbal <- balance + d - w
##         balance <<- newbal
##         newbal
##     }
## <environment: 0x104347158>

and the default function call will give us the balance in the account as illustrated next

John()
## [1] 100

Next, if John deposits 100, and makes a withdrawl for 50

John(d = 100, w = 50)

John will be left with.....???

John()
## [1] 150

In the next instanciation, we will create an account for Leo with 1000, and makes some action similar to John's account like above.

## We create an account for Leo with 1000 in it
Leo <- account(1000)
# Viewing Leo account function
Leo
## function(d = 0, w = 0) {
##         newbal <- balance + d - w
##         balance <<- newbal
##         newbal
##     }
## <environment: 0x1049676d8>

Note that the function definition of Leo, although identical to to John, has a different memory address

# we inspect the initial amount of Leo's account, and performs some
# transaction such as above for John
Leo()
## [1] 1000
Leo(d = 1000, w = 50)
## [1] 1950
Leo()
## [1] 1950
Leo(d = 100, w = 500)
## [1] 1550
Leo()
## [1] 1550

Inheritance - Continuation of the stack example

Now, we are going extend the "stack" class with new functionality via inheritance. Using the new_stack constructor, We are going to add "shift" and "unshift" methods and we can extend the "stack" object to a new class called "betterstack".

# The new_betterstack() is constructor of the object whose class is 'betterstack' and that is child/inherited from the object with class 'stack'
new_betterstack <- function() {

    # creating a stack object
    stack <- new_stack()
    # setting the enviroment of the stack object to a variable stack_env
    stack_env <- as.environment(stack)
    # Defining the new shift methods to stack object
    stack$shift <- function(x) .Data <<- c(x, .Data)
    # Defining the new unshift methods to stack object
    stack$unshift <- function() {
        tmp <- .Data[1]
        .Data <<- .Data[-1]
        return(tmp)
    }
    # setting the enviroment of stack$shift to the enviroment of stack
    environment(stack$shift) <- stack_env
    # setting the enviroment of stack$unshift to the enviroment of stack
    environment(stack$unshift) <- stack_env
    # setting the class attribute of newly created stack object
    class(stack) <- c("betterstack", "stack")
    # returning the object stack
    stack
}

Next we create shift and unshift methods to make the calls look more like normal R, to be used with the objects whose class is "betterstack"

shift <- function(x, value, ...) UseMethod("shift")
unshift <- function(x, ...) UseMethod("unshift")
shift.betterstack <- function(x, value, ...) x$shift(value)
unshift.betterstack <- function(x) x$unshift()

Now we illustrate the usage of the newly created "betterstack" object

nb <- new_betterstack()
push(nb, 1:3)
nb$.Data
## [1] 1 2 3
pop(nb)  # from the back
## [1] 3
unshift(nb)  # from the front
## [1] 1
shift(nb, 3)
push(nb, 1)
nb$.Data
## [1] 3 2 1

Finally, as Ryan mentioned in his post: Examples of Closures implementations can be found in the IBrokers package that interfaces the Interactive Brokers trading platform. See the twsConnect and eWrapper objects in the package on CRAN.

Further Notes on Knitr and Chunk's Options

  • http://www.rstudio.com/ide/docs/authoring/using_markdown
  • http://rpubs.com/gallery/options
  • http://yihui.name/knitr/options

Twitter feed section



R-Corner