New local variable behavior has three options, transient, persistent and global. The first default behavior, transient, is a faithful behavior to Ruby semantics. So, local variables vanish after each evaluation. Java programs can't get local variables used in Ruby scripts. If you want to use the same value or object as a local variable in more than one script, you need to reset it again and again. However, instance and global variables survive over the evaluations as those were in the previous version.
The second variable behavior, persistent, is the behavior that the previous version did. Thus, the same local variables can be used in multiple script evaluations. Also, those can be retrieved from Ruby and used in Java. As well as a local variable, an instance and global variables, and a constant are persistent over multiple evaluations.
Example for JRuby Embed API:
package brick;
import java.util.Map;
import java.util.Set;
import org.jruby.embed.ScriptingContainer;
import org.jruby.embed.LocalVariableBehavior;
public class Sample1 {
private Sample1() {
ScriptingContainer container = new ScriptingContainer(LocalVariableBehavior.PERSISTENT);
container.runScriptlet("p=9.0");
container.runScriptlet("q = Math.sqrt p");
container.runScriptlet("puts \"square root of #{p} is #{q}\"");
Map m = container.getVarMap();
Set<String> keys = container.getVarMap().keySet();
for (String key : keys) {
System.out.println(key + ", " + m.get(key));
}
System.out.println("Ruby used: p = " + container.get("p") +
", q = " + container.get("q"));
}
public static void main(String[] args) {
new Sample1();
}
}
Example for RedBridge (JSR223):
package redbridge;
import java.util.Set;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import org.jruby.embed.jsr223.JRubyScriptEngineManager;
public class EvalStringSample {
private EvalStringSample() throws ScriptException {
System.out.println("[" + getClass().getName() + "]");
System.setProperty("org.jruby.embed.localvariable.behavior", "persistent");
JRubyScriptEngineManager manager = new JRubyScriptEngineManager(Thread.currentThread().getContextClassLoader());
ScriptEngine engine = manager.getEngineByName("jruby");
engine.eval("p=9.0");
engine.eval("q = Math.sqrt p");
engine.eval("puts \"square root of #{p} is #{q}\"");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
Set<String> keys = bindings.keySet();
for (String key : keys) {
System.out.println(key + ", " + bindings.get(key));
}
System.out.println("Ruby used: p = " + engine.get("p") +
", q = " + engine.get("q"));
}
public static void main(String[] args) throws ScriptException {
new EvalStringSample();
}
}
Output:
square root of 9.0 is 3.0
MANT_DIG, 53
MAX_10_EXP, 308
DIG, 15
MIN_EXP, -1021
ROUNDS, 1
MAX, 1.7976931348623157E308
RADIX, 2
EPSILON, 2.220446049250313E-16
MIN, 4.9E-324
q, 3.0
p, 9.0
MIN_10_EXP, -307
MAX_EXP, 1024
Ruby used: p = 9.0, q = 3.0
The third variable behavior, global, is a backwards compatibility option for users who have used JSR223 reference implementation released form scripting.dev.java.net. The reference implementation (RI) uses Ruby's global variable to share variables between Java and Ruby. And the name of variables used in Java has the same form as the one of a local variable in Ruby. I mean, Java sees "message" while Ruby sees "$message." However, Embed API and RedBridge enable not only the global variable but also the instance and local variable and constant sharing. On Redbridge, when people use the name "message" in Java, they also use "message" in Ruby. When it is "$message" in Java, also, "$message" in Ruby. So that RI users can move on to RedBridge easily, I added this local variable behavior.
Example for RedBridge (JSR223):
# greetings_globalvars.rb
def greet
message = "How are you? #{$who}."
end
def sayhi
$, = ","
$\ = "\n"
print "Hi", $people
$, = ""
$\ = nil
end
def count
$people.size + 1
end
// OldVariableBehaviorSample.java
package redbridge;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import org.jruby.embed.jsr223.JRubyScriptEngineManager;
public class OldVariableBehaviorSample {
private final static String basedir = "/Users/yoko/NetBeansProjects/Birch";
private OldVariableBehaviorSample()
throws ScriptException, FileNotFoundException, NoSuchMethodException {
System.setProperty("org.jruby.embed.localvariable.behavior", "old");
JRubyScriptEngineManager manager = new JRubyScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
String filename = basedir + "/src/ruby/greetings_globalvars.rb";
Reader reader = new FileReader(filename);
engine.put("who", "Anakin");
Listpeople = new ArrayList ();
people.add("Obi-Wan");
people.add("C-3PO");
people.add("R2-D2");
engine.put("people", people);
engine.eval(reader);
Object[] args = null;
Object result = ((Invocable)engine).invokeFunction("greet", args);
System.out.println(result.toString());
((Invocable)engine).invokeFunction("sayhi", args);
result = ((Invocable)engine).invokeFunction("count", args);
System.out.println("counted: " + result.toString());
}
public static void main(String[] args)
throws ScriptException, FileNotFoundException, NoSuchMethodException {
new OldVariableBehaviorSample();
}
}
Output:
How are you? Anakin.
Hi,[Obi-Wan, C-3PO, R2-D2]
counted: 4
See wiki pages for details.
JRuby Embed API: http://kenai.com/projects/jruby-embed/pages/Home
RedBridge: http://kenai.com/projects/redbridge/pages/Home
No comments:
Post a Comment