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}"