Refs:

Library v8 is a Google’s open source JavaScript engine written in C++. The R package V8 provides a standalone JavaScript for R.

library(V8)

To execute JavaScript code we need a handler for a context, which is an execution environment:

ct <- new_context();

Within it, we can start programming:

ct$eval("var a = 1")
ct$get("a")
## [1] 1
ct$call("function(x, y){return x * y}", 123, 3)
## [1] 369

Make functions:

# make factorial function
# JS("...") means JavaScript literal code
ct$assign("fact",JS("
  function(n) {
    if (n==0)
      return 1;
    else
      return n*fact(n-1);
  }
"))

# use it
ct$eval("fact(6)")
## [1] "720"

We can export R data to JavaScript:

head(cars)
##   speed dist
## 1     4    2
## 2     4   10
## 3     7    4
## 4     7   22
## 5     8   16
## 6     9   10
ct$assign("mydata", cars)
head(ct$get("mydata"))
##   speed dist
## 1     4    2
## 2     4   10
## 3     7    4
## 4     7   22
## 5     8   16
## 6     9   10

Validate expressions without evaluation:

ct$validate("function foo(x){2x}")
## [1] FALSE
ct$validate("function foo(x){2*x}")
## [1] TRUE
ct$validate("function(x){2*x}")
## [1] FALSE
ct$validate("(function(x){2*x})") # for anonymous functions, wrap them in ()'s
## [1] TRUE

We can create JSON descriptions of some data structure:

ct$eval("JSON.stringify({x:Math.random()})")
## [1] "{\"x\":0.9207249612081796}"

Use JavaScript libraries:

ct$source(system.file("js/underscore.js", package="V8")) # js lib for functional programming
ct$call("_.filter", mtcars, JS("function(x){return x.mpg < 15}"))
##                      mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Duster 360          14.3   8  360 245 3.21 3.570 15.84  0  0    3    4
## Cadillac Fleetwood  10.4   8  472 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8  460 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8  440 230 3.23 5.345 17.42  0  0    3    4
## Camaro Z28          13.3   8  350 245 3.73 3.840 15.41  0  0    3    4

Place new js libraries under [your R]\library\V8\js.

Notice that we can have more than one context:

ct$eval("var x = 1")

ct2 <- new_context();
ct2$eval("var x = 2") # the variable is in a 2nd context

ct$get("x")
## [1] 1
ct2$get("x")
## [1] 2

To erase a context use ct$reset().

It’s also possible to make an interactive console by typing ct$console(). To end it, type exit.

Another eg where we create and use a composition operator for tuples (this is a pseudo-monad in JavaScript):

ct$eval('
     // tuple composition
     gName = function(name) {   // change name
          return function(g) { 
              g.name = name; 
              return g; 
          }; 
     };
     
     gType = function(type) {   // change type
          return function(g) { 
              g.type = type; 
              return g; 
          }; 
     };
      
     c = function(g, op) {      // tuple composition operator
          return op(g)
     };

     // show tuple

     showtuple = function(g) {
          return "tuple: {name:" + g.name + ", type:" + g.type + "}";
     };
              
     // make a tuple 

     tuple = { name : "a",
               type : "b" };  // a tuple eg
')
## [1] "[object Object]"

ct$eval('showtuple(tuple);')
## [1] "tuple: {name:a, type:b}"
ct$eval('newTuple = c(c(tuple, gName("new_a")), gType("new_b"));')
## [1] "[object Object]"
ct$eval('showtuple(newTuple);')
## [1] "tuple: {name:new_a, type:new_b}"