Learn R Programming

rscala (version 1.0.6)

eval: Execute code, set values, and get values in an embedded interpreter.

Description

These functions define the package's interface to an embedded interpreter. Through these functions, code is executed in the embedded interpreter and data is passed between Rand the embedded interpreter. Some of these functions return a function for invoking a function in the interpreter. Others return a reference to the result or attempt to return an Robject representing the result. Some functions also provide the ability to clear variables or reclaim memory previously allocated to references. There are convenient shorthand equivalents for many of the functions.

Usage

intpEval(interpreter, snippet, interpolate="", quiet="")
intpGet(interpreter, identifier, as.reference=NA)
intpSet(interpreter, identifier, value, length.one.as.vector="", quiet="")
intpDef(interpreter, args, body, interpolate = "", quiet = "", reference=NULL)
intpWrap(interpreter, value)
intpUnwrap(interpreter, value)
intpGC(interpreter)
intpReset(interpreter)
scalap(interpreter, item.name)

interpreter %~% snippet interpreter %.~% snippet

## S3 method for class 'ScalaInterpreter': $(interpreter, identifier) ## S3 method for class 'ScalaInterpreter': $(interpreter, identifier) <- value

Arguments

interpreter
An interpreter from an interpreter constructor (i.e. scalaInterpreter).
snippet
A character vector of arbitrary length to be evaluated by the interpreter.
args
A character vector of length one giving the argument list for a function to be defined in the interpreter. Use "" for a function which takes no arguments.
body
A character vector of any length giving the body for a function to be defined in the interpreter. The function body can be a multiline character vector of length one.
identifier
A character vector of length one containing a valid variable name in the embedded language.
value
For intpWrap, an arbitrary R object. For intpUnwrap, a result of a call to intpWrap. For
as.reference
A logical vector of length one indicating whether the result of intpGet should return a reference to the function result or whether these functions should try to interpret the result as a vector or matrix o
interpolate
When equal to "" (the default), the default behavior from intpSettings is used. If equal to TRUE, the interpreter will call strintrpl
length.one.as.vector
When equal to "" (the default), the default behavior from intpSettings is used. If equal to TRUE, setting a vector of length one in the interpreter will result in an array of
quiet
When equal to "" (the default), the default behavior from intpSettings is used. Otherwise, console output from the interpreter will be displayed if TRUE and will be suppresse
reference
This option is meant only for developers of the package itself and not intended for users of the package.
item.name
A character vector of length one containing the name of an object/class for which the scalap command should be run.

Value

  • intpEval, intpSet, intpGC, and intpReset silently return NULL.

    intpGet returns a reference to the result if as.reference is TRUE. If as.reference is FALSE, the function tries to convert the result to a vector or matrix of integers, doubles, logicals, or characters. If a conversion is not possible, NULL is silently returned.

    intpDef returns an Rfunction that calls the corresponding function defined by the args and body. In addition to the arguments specified in args, the resulting function also has named arguments as.reference, quiet, and gc. The first two have the same behavior as described above. The gc argument specifies whether the interpreter's garbage collector should be run to free references. The default is FALSE for performance reasons. Instead of setting gc to TRUE, it is recommended that the function intpGC be periodically run if many references from a function returned by intpDef are generated.

Details

The convenient shorthand notation interpreter %~% snippet both evaluates the expression snippet and attempts to return a vector or matrix of integers, doubles, logicals, or characters or --- if this is not possible --- NULL is returned. The convenient shorthand notation interpreter %.~% snippet has the same behavior except it always returns a reference. References may be used later as the value in intpSet or as an argument to a function returned by intpDef. Note, however, the memory associated with values returned by %~% and %.~% is never garbage-collected. Likewise, memory allocated in the global environment of the Scala interpreter is never garbage-collected. (See the Scala bug detailed here: https://issues.scala-lang.org/browse/SI-4331.)

Memory associated with the return values by function defined by intpDef, however, is able to be garbage-collected. Thus, heavy usage of functions defined by intpDef is encouraged for memory intensive applications. (Use intpGC to invoke the interpreter's garbage collector.) Further, functions defined by intpDef have less invocation latency than the equivalent code using %~% and %.~%. The speed difference in invocation is especially noticable for quick functions.

The convenient shorthand notations interpreter$identifier and interpreter$identifier <- value make it easy to get and set variables in the interpreter. Note, however, that def is a reserved word in Scala and, as such, is treated as a special case: interpreter$def(args,body) is equivalent to intpDef(interpreter,args,body). See the examples below.

See Also

scalaInterpreter, intpSettings, strintrplt

Examples

Run this code
# Get an instance of a Scala interpreter and see the default settings
s <- scalaInterpreter()
intpSettings(s)

# Demonstrate convenient notation and string interpolation
s %~% 'println("Hello @{Sys.getenv("USER")}")'
intpEval(s,'println("Hello again")')             # Results printed to console
intpEval(s,'println("Hello again")',quiet=TRUE)  # Console output is suppressed

# Set and get variables
s$rPi <- pi
s$rPi

# Make vectors of length one be set as arrays
intpSettings(s,length.one.as.vector=TRUE)

# Unlike above, now 'pi' is set as an array of length one
s$rPi <- pi
intpGet(s,"rPi")
intpGet(s,"rPi",as.reference=TRUE)              # Get the result as a reference
intpSet(s,"rPi",pi,length.one.as.vector=FALSE)  # Override current global setting
intpSettings(s,length.one.as.vector=FALSE)      # Put it back to the default

# Convenient notation
a1 <- s %~%  "rPi/2"   # As an R value
a2 <- s %.~% "rPi/2"   # As a reference

# References can be set
s$foo <- a2

# Change default to suppress output
intpSettings(s,quiet=TRUE)
s %~% 'println("Hello")'
intpEval(s,'println("Hello")')
intpEval(s,'println("Hello")',quiet=FALSE)  # But the default can be overridden

# Get a reference to an R object
myList <- list(a=2, b=matrix(1:8,nrow=2))
wrappedList <- intpWrap(s,myList)
identical(myList,intpUnwrap(s,wrappedList))
s$.myList <- myList
identical(myList,s$myList)

# Instantiate an object
seed <- 2349234L
scalap(s,'scala.util.Random')
rng <- s$do('scala.util.Random')$new(seed)  # Scala equivalent: new scala.util.Random(seed)

# Call method of a reference
system.time(rng$nextInt(100L))   # Scala equivalent: rng.nextInt(100)
system.time(rng$nextInt(100L))   # Notice it runs much faster after the first time.

# Call method of companion object and call methods of a reference
# Scala equivalent: (scala.math.BigInt('777',8) - 500).intValue
s$do('scala.math.BigInt')$apply('777',8L)$'-'(500L)$intValue()

# Longer example showing that 'intpDef' is more flexible and faster than '%~%'
intpSet(s,"rng",rng)
drawGaussian <- intpDef(s,'mean: Double, sd: Double','mean+sd*rng.nextDouble')
drawGaussian(3,0.1)
n.draws <- 100
system.time({
  draws <- s %~% '
    val result = new Array[Double](@{n.draws})
    result(0) = rng.nextGaussian
    for ( i <- 1 until @{n.draws} ) {
      result(i) = 0.5*result(i-1) + rng.nextGaussian
    }
    result
  '
  acf(draws,plot=FALSE)
})
sampler <- s$def('nDraws: Int, rho: Double','
  val result = new Array[Double](nDraws)
  result(0) = rng.nextGaussian
  for ( i <- 1 until nDraws ) {
    result(i) = rho*result(i-1) + rng.nextGaussian
  }
  result
')
system.time(acf(sampler(n.draws,0.5),plot=FALSE))
system.time(acf(sampler(n.draws,0.9),plot=FALSE))

Run the code above in your browser using DataLab