- GraalVM for JDK 23 (Latest)
- GraalVM for JDK 24 (Early Access)
- GraalVM for JDK 21
- GraalVM for JDK 17
- Archives
- Dev Build
Interoperability
GraalVM supports several other programming languages including JavaScript, Ruby, Python, and those that compile to LLVM bitcode.
GraalVM’s R runtime provides an API for programming language interoperability that lets you execute code from any other GraalVM-supported language.
Note that you must start the R script with --polyglot
to have access to other languages.
GraalVM’s R runtime allows the following interoperability primitives:
eval.polyglot('languageId', 'code')
evaluates code in some other language. ThelanguageId
can be, e.g.,js
.eval.polyglot(path = '/path/to/file.extension')
evaluates code loaded from a file. The language is recognized from the extension.export('polyglot-value-name', rObject)
exports an R object so that it can be imported by other languages.import('exported-polyglot-value-name')
imports a polyglot value exported by some other language.
Use the ?functionName
syntax to learn more. The following example demonstrates the interoperability features:
# get an array from Ruby
x <- eval.polyglot('ruby', '[1,2,3]')
print(x[[1]])
# [1] 1
# get a JavaScript object
x <- eval.polyglot(path='r_example.js')
print(x$a)
# [1] "value"
# use R vector in JavaScript
export('robj', c(1,2,3))
eval.polyglot('js', paste0(
'rvalue = Polyglot.import("robj"); ',
'console.log("JavaScript: " + rvalue.length);'))
# JavaScript: 3
# NULL -- the return value of eval.polyglot
(Uses r_example.js.)
R vectors are presented as arrays to other languages.
This includes single element vectors, e.g., 42L
or NA
.
However, single element vectors that do not contain NA
can be typically used in places where the other languages expect a scalar value.
An array subscript or similar operation can be used in other languages to access individual elements of an R vector.
If the element of the vector is not NA
, the actual value is returned as a scalar value, e.g., int
.
If the element is NA
, then a special object that looks like null
is returned.
The following Ruby code demonstrates this:
vec = Polyglot.eval("R", "c(NA, 42)")
p vec[0].nil?
# true
p vec[1]
# 42
vec = Polyglot.eval("R", "42")
p vec.to_s
# "[42]"
p vec[0]
# 42
The foreign objects passed to R are implicitly treated as specific R types. The following table gives some examples:
Example of foreign object (Java) | Viewed ‘as if’ on the R side |
---|---|
int[] {1,2,3} | c(1L,2L,3L) |
int[][] { {1, 2, 3}, {1, 2, 3} } | matrix(c(1:3,1:3),nrow=3) |
int[][] { {1, 2, 3}, {1, 3} } | not supported: raises error |
Object[] {1, ‘a’, ‘1’} | list(1L, ‘a’, ‘1’) |
42 | 42L |
In the following example, we can simply pass the Ruby array to the R built-in function sum
, which will work with the Ruby array as if it was an integer vector.
sum(eval.polyglot('ruby', '[1,2,3]'))
Foreign objects can be also explicitly wrapped into adapters that make them look like the desired R type. In such a case, no data copying occurs, if possible. The code snippet below shows the most common use cases:
# gives list instead of an integer vector
as.list(eval.polyglot('ruby', '[1,2,3]'))
# assume the following Java code:
# public class ClassWithArrays {
# public boolean[] b = {true, false, true};
# public int[] i = {1, 2, 3};
# }
x <- new('ClassWithArrays'); # see Java interop below
as.list(x)
# gives: list(c(T,F,T), c(1L,2L,3L))
For more details, refer to the executable specification of the implicit and explicit foreign objects conversions.
Note: R contexts started from other languages, or Java (as opposed to via the R
script), will default to non interactive mode, similar to Rscript
.
This has implications on console output (the results are not echoed) and graphics (the output defaults to a file instead of a window), and some packages may behave differently in non-interactive mode.
Bellow is a list of available R interoperability builtin functions.
For more information see the R --help
message and try these examples:
> help(java.type)
> ?java.type
> example(java.type)
java.type
java.addToClasspath
is.polyglot.value
eval.polyglot
export
import
See the Polyglot Programming reference for more information about interoperability with other programming languages.