Использование Lisp или схемы для конфигурации времени выполнения Java-программ

Теперь я видел несколько проектов, заканчивающихся в точке, где фактическая конфигурация зависела от вещей, доступных только во время выполнения.

Типичным способом настройки программы Java является чтение одного или нескольких файлов свойств в соответствии с некоторыми конкретными правилами приложения, а затем принятие действий в зависимости от их значений. В какой-то момент это прерывается, и вам нужна фактическая программная логика в вашей конфигурации, которая затем может быть указана с флагом и добавлением кода в ваше приложение, которое затем обрабатывает флаг.

Мне было интересно, может ли быть лучшим вариантом для модуля чтения конфигурации Lisp, где считываемый файл не является файлом свойств, а программой Lisp, который затем оценивается для создания окончательной структуры данных, представляющей конфигурации. Минимальный набор функций в библиотеке времени выполнения позволял бы манипулировать строкой и, возможно, даже вызывать в JVM. Просто подумайте о "создании URL-адреса на основе текущего имени хоста".

Меня не интересует полный движок Lisp с колокольчиками, а для этой цели - небольшая библиотека, которая может быть заключена в даже небольшие программы без большой банки, содержащей механизм Lisp.

Итак, существует ли такая библиотека?

  • Малый размер
  • Просто нужно прочитать файл + eval и возможность читать результирующую структуру данных из основной программы Java
  • Небольшая библиотека времени Lisp
  • Скорость имеет меньшее значение.
  • Активно поддерживается.

Предложения?


Редактировать 2012-01-20: Первоначально я обнаружил, что все кандидаты нежелательны, но решили использовать это как упражнение Maven на стороне с выпуском jscheme 1.4 в 1998 году. Проект https://github.com/ravn/jscheme-1998


Edit 2012-12-11: Оказалось, что уровень интеграции между программой, интерпретируемой в Scheme, и основной программой Java, был более важным, чем я думал раньше, и что мне нужно было в проекте, чтобы иметь возможность предоставлять классы с аннотациями JAX-WS во время выполнения, что я не мог сделать с JScheme, но я мог бы сделать с Groovy. Идея небольшой библиотеки конфигурации, которая позволяет фрагменты кода в библиотеках, по-прежнему действительна, но мне все же нужно было больше, чтобы она была полезной.

Ответ 1

Я знаю, что вы хотите небольшой размер и время исполнения. Схема - это обычный выбор для легкого внедрения, и это будет мой первый выбор. Но у меня нет информации об этой области. Мой второй выбор Clojure:

  • Не так мало; банка ~ 3 МБ
  • Overkill для простого чтения конфигурации, но дополнительные функции можно безопасно игнорировать.
  • ~ Простота вызова из Java: Вызов clojure из java
  • Полный, отличный доступ к JVM
  • Может потребоваться небольшая добавка к запуску, что может быть слишком большим (см. ниже)
  • Теперь, когда я попытался воспроизвести функциональность примера с помощью Clojure, я чувствую, что clojure не подходит для этих типов скриптов (rc и т.д.). clojure 1.3 рассмотрит некоторые из этих штрафных очков за запуск, но я не знаю, насколько скоро будут достигнуты улучшения скорости.

Соответствующий код с использованием Clojure:

import clojure.lang.RT;
import clojure.lang.Var;
import clojure.lang.Compiler;
import java.io.FileReader;
import java.io.FileNotFoundException;

public class ClojTest {
    public static void main(String[] args) throws Exception {
        try {
            Compiler.load(new FileReader("hello.clj"));
        } catch(FileNotFoundException e) { return; }

        System.out.println("Message: '"+ RT.var("user", "msg").get() +"'");

        // Values
        int answer = (Integer) RT.var("user", "answer").get();

        // Function calls
        System.out.println(RT.var("user", "countdown").invoke(42));
    }
}

с hello.clj:

(ns user)
(defn countdown [n]
  (reduce + (range 1 (inc n))))

(def msg "Hello from Clojure!")
(def answer (countdown 42))

Запуск time java ClojTest на некоторое время дает в среднем 0,75 секунды. clojure компиляция script имеет довольно штраф!

Ответ 2

Хорошее, гораздо меньшее решение - встроенная схема для Java. Из многих реализаций я нашел и протестировал JScheme. (API выглядит нормально: http://jscheme.sourceforge.net/jscheme/doc/api/index.html)

Простая основная программа в Java:

import jscheme.JScheme;
import jscheme.SchemeException;
import java.io.*;
public class SchemeTest {
    public static void main(String[] args) {
        JScheme js = null;
        try {
            js = new JScheme();
            js.load(new FileReader("config.scm"));
        } catch (FileNotFoundException e) { return; }

        System.out.println("Message: '" + js.eval("msg") + "'");

        // Values
        int answer = (Integer) js.eval("answer");

        // Function calls
        System.out.println(js.call("countdown", 42));
    }
}

И пример config.scm:

(define (countdown x)
  (define (loop x acc)
    (if (= x 0)
      acc
      (loop (- x 1) (+ acc x))))
  (loop x 0))

;;; config variables
(define msg "Hello from JScheme!")
;; tail calls are optimized as required
(define answer (countdown 42))

Схема интерпретируется при запуске каждый раз, поэтому это хороший выбор для конфигураций. К преимуществам JScheme относятся:

  • хорошая интеграция с JVM
  • по-видимому, полная реализация схемы
  • маленький размер (572 kB)
  • быстрый, несколько легко вызываемый из Java

Обновление производительности: этот код работает 0,13 секунды. По сравнению с временем версии Clojure это довольно быстро.

Ответ 3

Попробуйте SISC, это довольно маленькая (300kb jar) реализация Схемы без колоколов и свистов. Склеивание его с помощью Java является тривиальным, и скорость выполнения довольно впечатляет для чистого интерпретатора.

Ответ 4

Clojure отлично, он встраивается и имеет очень хорошую совместимость для вызова библиотек Java. Однако это не особенно мало (вы получаете полный компилятор и довольно приличную библиотеку времени исполнения). По-прежнему стоит подумать, есть ли у вас более широкое требование для такого рода функций. Я нашел Clojure для работы как отличный динамический "клей" для Java-кода.

В противном случае лучший выбор - это, вероятно, крошечный встроенный интерпретатор Scheme.

Возможно, можно использовать раннюю (1998) версию JScheme по этой ссылке, которая представляет собой только файл с размером файла 30 000: http://norvig.com/jscheme.html

В противном случае, возможно, возможно написать что-то еще более минимальное в нескольких сотнях строк Java... это, вероятно, только проект на выходные, учитывая, насколько мал ядро ​​Scheme. Следующая страница довольно интересна, если вы хотите написать мини-интерпретатор для Схемы: http://archives.evergreen.edu/webpages/curricular/2000-2001/fofc00/eval.html