$ rvm jruby-1.6.4
$ irb
jruby-1.6.4 :001 > require 'java'
=> true
jruby-1.6.4 :002 > $CLASSPATH << "/Users/yoko/Tools/clojure-1.3.0"
=> ["file:/Users/yoko/Tools/clojure-1.3.0/"]
jruby-1.6.4 :003 > require 'clojure-1.3.0-slim'
=> true
jruby-1.6.4 :004 > h = {"a" => 100, "b" => 300, "c" => 200}
=> {"a"=>100, "b"=>300, "c"=>200}
jruby-1.6.4 :005 > pmap = Java::clojure.lang.PersistentHashMap.create(h)
=> {"a"=>100, "b"=>300, "c"=>200}
jruby-1.6.4 :006 > pmap.class
=> Java::ClojureLang::PersistentHashMap
OK. I could successfully create Clojure's PersistentHashMap object. PersistentHashMap implements java.util.Map interface, which means the object has all of Ruby's Hash methods.
jruby-1.6.4 :007 > pmap.each {|k, v| puts "#{k} is #{v}"}
a is 100
b is 300
c is 200
=> {"a"=>100, "b"=>300, "c"=>200}
jruby-1.6.4 :008 > pmap.select {|k, v| k > "a"}
=> [["b", 300], ["c", 200]]
jruby-1.6.4 :009 > pmap.has_value?(400)
=> false
PersistenHasMap is immutable. So, when the method tries to change its data, Clojure raises exception:
jruby-1.6.4 :012 > pmap.delete_if {|k, v| k >= "b"}
Java::JavaLang::UnsupportedOperationException:
from clojure.lang.APersistentMap.remove(APersistentMap.java:273)
from org.jruby.java.proxies.MapJavaProxy$RubyHashMap.internalDelete(MapJavaProxy.java:157)
from org.jruby.RubyHash.delete(RubyHash.java:1407)
(snip)
This way, we can use Clojure's immutable data types on JRuby.
4 comments:
For this to be interesting, you'd need Clojure concurrency primitives like dosync and send, right?
Yes. People are often concerned about thread safety. Clojure's idea on concurrency might work well on JRuby, too.
Cool. For what it's worth, I recently started an experiment that exposes most of Clojure (no macros) to JRuby. Here it is. It will probably need a lot of work, especially performance, for real work, but it's kind of fun.
dr: Wow, that's a nice Ruby wrapper. I think there's a way of implementing by JRuby extension. You can mix simple Ruby wrapper and extension methods.
Post a Comment