Использование JRuby / Jython для совместимости Ruby / Python? - PullRequest
11 голосов
/ 02 мая 2010

Довольно, наверное, глупый вопрос, так как я не очень разбираюсь в Java / Jython / JRuby / bytecode, но ..

Сегодня я снова наткнулся на _why's unholy . Он позволяет вам выводить байт-код Python из кода Ruby .. По сути, он позволяет им генерировать один и тот же байт-код ..

Jython выводит Java-байт-код, как и JRuby. Поскольку оба компилируются в один и тот же байт-код, означает ли это, что вы потенциально можете использовать любую библиотеку Python из Ruby и библиотеки Ruby из Python?

Ответы [ 2 ]

7 голосов
/ 02 мая 2010

Нет, это не сработает. По крайней мере, не так, как вы думаете.

Функциональная совместимость между Jython и JRuby работает так же, как между CPython и YARV: они оба работают на одной платформе, поэтому они могут общаться друг с другом с помощью этой платформы.

В случае CPython и YARV этой платформой является C / POSIX, поэтому они могут взаимодействовать друг с другом с помощью структур C, int s, char* s и вызовов функций C. В случае Jython и JRuby эта платформа является JVM, поэтому они могут взаимодействовать друг с другом, используя объекты JVM, классы JVM, интерфейсы JVM, типы JVM и методы JVM.

В обоих случаях эти примитивы платформы выглядят ничем как объекты Python или Ruby.

Для JRuby Jython - это просто еще одна Java-программа. Для Jython JRuby - это просто еще одна Java-программа.

Например: в Ruby вы можете динамически добавлять, удалять и переопределять методы в любой момент. В JVM наименьшая единица кода, которую можно динамически добавлять и удалять, - это класс. Таким образом, метод Ruby на самом деле не представлен как метод Java. Он представлен в виде Java class . И логически, объект Ruby с парой методов представляется как объект Java без методов, только поле Dictionary<String, RubyMethod>. IOW: он полностью непригоден для Java, и, поскольку с точки зрения JRuby Jython - это просто Java, он также непригоден для Jython.

Теперь, есть способов сделать это немного лучше. Вы можете использовать настоящие типы Java для связи между двумя & ndash; обе реализации имеют отличную совместимость с Java. Таким образом, вместо передачи хэша Ruby в Python или словаря Python в Ruby, вы должны использовать Java Map из Ruby и Python. Но обратите внимание, что для этого необходимо, чтобы и ваш код на Ruby и Python были специально написаны для работы на JVM. IOW: вы не можете просто использовать любую библиотеку Python или Ruby, которую найдете в сети, о чем вы и просите.

Еще одна возможность, упомянутая @duncan в его ответе: встроить Jython или JRuby в качестве механизма сценариев в ваше приложение на Ruby или Python. Но опять же, это не совсем отвечает на ваш вопрос об использовании произвольных библиотек Python из Ruby или наоборот.

Итак, в чем здесь проблема?

Проблема в том, что для взаимодействия двух сред выполнения они должны говорить на одном и том же «языке». И в этом конкретном случае единственным языком, который имеет две среды выполнения, является Java, или, скорее, сильно ограниченное подмножество Java.

Итак, нам нужно найти общий язык. Одним из способов определения такого языка было бы, чтобы обе среды выполнения понимали протокол мета-объектов (MOP) друг друга.

MOP - это в основном объектная модель для объектной модели языка. Хм, это сбивает с толку, потому что мы используем слово «объектная модель» для обозначения двух разных вещей. Позвольте мне перефразировать это:

MOP - это в основном доменная модель для объектной системы языка. Точно так же, как доменная модель для банковской системы содержит объекты, которые представляют реальных клиентов, счета, балансы, бухгалтерские книги и т. Д., И методы, которые представляют реальные действия, такие как денежные переводы, снятие и т. Д., MOP содержит объекты, которые представляют языковые классы, методы, переменные, объекты и методы, которые представляют языковые действия, такие как поиск переменной, вызов метода, наследование от класса, создание экземпляра класса.

Обычно каждая среда выполнения сохраняет свою MOP частной, а каждая среда выполнения имеет свою собственную MOP.

Если JRuby и Jython выставляли свои MOP друг другу и понимали MOP друг друга (или, что еще лучше: они выставляли свои MOP для JVM и оба использовали один и тот же MOP), тогда вы могли бы передать один из этих сумасшедших пакетов методов JRuby для Jython, и он будет знать, как найти методы, принадлежащие этому объекту, и как их вызывать, потому что он может просто спросить MOP JRuby, как это сделать.

На самом деле существует проект по созданию именно такой MOP для JVM: dynalang MOP - это проект для общей стандартизированной MOP для динамических языков, работающих на JVM. Он был создан Аттилой Сегеди, разработчиком движка Mozilla Rhino ECMAScript. На данный момент ни одна из крупных языковых реализаций не использует его, но по крайней мере Rhino, JRuby, Jython и Groovy ведется совместная работа, чтобы убедиться, что dynalang достаточно универсален, чтобы поддерживать все объектные модели различных языков.

Если вы хотите взглянуть на то, как будет выглядеть мир с таким общим MOP, вы можете взглянуть на Microsoft Dynamic Language Runtime (DLR). DLR содержит именно такую ​​MOP и все среды выполнения, которые поддерживают DLR (которая, в дополнение к обычным подозреваемым, таким как IronRuby , IronPython , IronJS и IronScheme теперь также включает в себя C # 4 и Visual Basic.NET 10), может практически беспрепятственно взаимодействовать друг с другом.

Другой похожей платформой является Parrot Virtual Machine , которая была специально разработана для взаимодействия нескольких динамических языков на одной платформе времени выполнения. Доступны реализации Python ( Pynie ) и Ruby ( Cardinal ), но особенно Cardinal все еще очень далека от того, чтобы быть даже удаленно полной реализацией Ruby.

5 голосов
/ 02 мая 2010

Есть два способа сделать это. Оба предлагают возможность статической компиляции кода и создания реального класса Java из сценария. Jython AFAIK в этом случае генерирует исходный код Java и затем вызывает javac через скрипт jythonc. Но это требует компиляции.

Для обоих интерпретаторов вы можете вызывать код Java из сценариев и встраивать интерпретатор в приложение Java.

Например, чтобы вызвать Java из Python:

>>> from java.util import Random
>>> r = Random()
>>> r.nextInt()
501203849

Чтобы встроить интерпретатор JRuby в Java, вы можете сделать это (обратите внимание, что также есть способ на основе JSR223, это основной):

package vanilla;

import org.jruby.embed.ScriptingContainer;

public class HelloWorld {

    private HelloWorld() {
        ScriptingContainer container = new ScriptingContainer();
        container.runScriptlet("puts Hello world");
    }

    public static void main(String[] args) {
        new HelloWorld();
    }

Вы можете сделать то же самое с Jyton (я думаю, вам нужно будет правильно указать пути jruby):

import org.jruby.embed.ScriptingContainer
container = ScriptingContainer()
container.runScriptlet("puts Hello world")

То же самое можно сделать и наоборот.

Вы не получите весь ruby ​​stdlib, экспортированный в интерпретатор python, выполнив импорт. Вам необходимо заранее скомпилировать stdlib для ruby ​​в байт-код.

Однако, используя описанную выше технику и добавив пару вспомогательных сценариев и определенных интерфейсов, вы можете соединить определенные функции от одного языка к другому.

...