How to Get from Jruby a Correctly Typed Ruby Implementation of a Java Interface

How to get from JRuby a correctly typed ruby implementation of a Java interface?

It should be, but unfortunately isn't quite wired up that way yet. For now, #java_implements and #java_signature are only used by the jrubyc --java command that creates a Java source file based on the Ruby class. You may want to consider using that for your Ruby integration.

We're aiming for this example to work for both precompiled scripts and runtime-executed scripts in the future. If you instead want this script to work as intended, try using include Java::some.package.ScriptDemoIf instead of java_implements.

JRuby: command pattern in Java with Ruby block: why does it work?

The reason that this works is a feature called 'closure conversion' (see docs here). What happens is that the block you pass is converted into a Proc object with a proxy that invokes the code in the block for any method that is called on the object.

Can I return an anonymous closure in JRuby when an interface is expected?

yes - you should be able to do just that ... just use to_java on a proc/lambda :

class Child < Parent
def getIt
lambda { |*args| puts args.inspect }.to_java(Java::MyInterface)
end
end

Using JRuby/Jython for Ruby/Python interoperability?

No, that won't work. At least not the way you think it would.

Interoperability between Jython and JRuby works the same way as between CPython and YARV: they both run on the same platform, so they can communicate with each other using that platform.

In the case of CPython and YARV, that platform is C/POSIX, so they can communicate with each other using C structs, ints, char*s and C function calls. In the case of Jython and JRuby, that platform is the JVM, so they can communicate with each other using JVM objects, JVM classes, JVM interfaces, JVM types and JVM methods.

In both cases, those platform primitives look nothing like Python or Ruby objects.

To JRuby, Jython is just yet another Java program. To Jython, JRuby is just another Java program.

For example: in Ruby, you can add, remove and redefine methods dynamically at any moment. On the JVM, the smallest unit of code that can be dynamically added and removed is a class. So, a Ruby method is actually not represented as a Java method. It is represented as a Java class. And logically, a Ruby object with a couple of methods is represented as a Java object with no methods, just a Dictionary<String, RubyMethod> field. IOW: it's totally unusable from Java, and, since from JRuby's point of view Jython is just Java, it's also unusable from Jython.

Now, there are ways to make this a little bit better. You could use actual Java types to communicate between the two – both implementations have great interoperability with Java. So, instead of passing a Ruby hash to Python or a Python dictionary to Ruby, you would use a Java Map from both Ruby and Python. But note that this requires that both your Ruby and Python code are specifically written to work on the JVM. IOW: you cannot just use any Python or Ruby library you find on the web, which is what you are asking about.

Another possibility is the one mentioned by @duncan in his answer: embed Jython or JRuby as a scripting engine into your Ruby or Python application. But again, this doesn't really answer your question about using arbitrary Python libraries from Ruby or vice versa.

So, what is the problem here?

The problem is that in order for the two runtimes to communicate, they need to speak the same "language". And in this particular case, the only language that the two runtimes have in common, is Java, or rather a severely crippled subset of Java.

So, we need to find a common language. One way to define such a language would be for both runtimes to understand each other's Meta-Object Protocol (MOP).

A MOP is basically an object model for the language's object model. Um, that's confusing because we use the word "object model" to mean two different things. Let me rephrase that:

A MOP is basically a domain model for the language's object system. Just like a domain model for a banking system contains objects that represent real-world customers, accounts, balances, ledgers and so on, and methods that represent real-world actions like money transfers, withdrawals and so on, a MOP contains objects that represent language classes, methods, variables, objects and methods that represent language actions like looking up a variable, calling a method, inheriting from a class, constructing an instance of a class.

Normally, every runtime keeps its MOP private, and every runtime has its own MOP.

If JRuby and Jython exposed their MOPs to each other and understood each other's MOPs (or, even better yet: they exposed their MOPs to the JVM and both used the same MOP), then you could pass one of those crazy JRuby method bags to Jython, and it would know how to find the methods that belong to that object and how to call them, because it can just ask JRuby's MOP how to do it.

There is actually a project to create just such a MOP for the JVM: the dynalang MOP is a project for a shared, standardized MOP for dynamic languages running on the JVM. It was created by Attila Szegedi, the maintainer of the Mozilla Rhino ECMAScript engine. At the moment, none of the big language implementations uses it, but there is collaboration going on between at least Rhino, JRuby, Jython and Groovy to make sure that dynalang is generic enough that it can support all of the different language's object models.

If you want a sneak peek at what a world with such a shared MOP would look like, you can take a look at Microsoft's Dynamic Language Runtime (DLR). The DLR contains just such a MOP and all runtimes which support the DLR (which, in addition to the usual suspects such as IronRuby, IronPython, IronJS and IronScheme now also includes C# 4 and Visual Basic.NET 10) can almost seamlessly interoperate with each other.

Another similar platform is the Parrot Virtual Machine, which was specifically designed to allow multiple dynamic languages to interoperate on the same runtime platform. There are implementations of Python (Pynie) and Ruby (Cardinal) available, but especially Cardinal is still very far from being even a remotely complete Ruby implementation.

Interfaces & Abstract Classes unnecessary in Ruby -- Can someone explain?

I am also Ruby starter. From my understanding, there is a closer rival for abstract classes in ruby. that is module. you can't create any instances of module but you can include with another class. So a target class will get the whole functionality of parent

  module Log
def write
//blah
end
end

class EventLog
include Log

def Prepare
end
end

In statically typed languages like java/C# , Interfaces enforce the classes to have all the methods at compile time. Since Ruby is dynamic, there is no meaning in it.

For more clarity, check these posts why dynamic languages don't require interfaces..

  1. why-dont-we-require-interfaces-in-dynamic-languages
  2. why-do-dynamic-languages-like-ruby-and-python-not-have-the-concept-of-interfaces

Cheers

Advantages of Java over Ruby/JRuby

I don't know Ruby very well, but I can guess the following points:

  • Java has more documentation (books, blogs, tutorial, etc.); overall documentation quality is very good
  • Java has more tools (IDEs, build tools, compilers, etc.)
  • Java has better refactoring capabilities (due to the static type system, I guess)
  • Java has more widespread adoption than Ruby
  • Java has a well-specified memory model
  • As far as I know, Java has better support for threading and unicode (JRuby may help here)
  • Java's overall performance is quite good as of late (due to hotspot, G1 new garbage collector, etc.)
  • Nowadays, Java has very attractive and cheap server hosting: appengine

Jython script implementing a class isn't initialized correctly from Java

What version of jython are you using? You might have run into the JSR223 Jython bug : http://bugs.jython.org/issue1681

From the bug description:

Calling methods from an embedded Jython script does nothing when
using JSR-223 and Jython 2.5.2rc2, while Jython 2.2.1 just works fine.



Related Topics



Leave a reply



Submit