Как я могу создать один исходный файл Clojure, который можно безопасно использовать как скрипт и библиотеку без компиляции AOT? - PullRequest
1 голос
/ 27 января 2012

Я потратил некоторое время на изучение этого вопроса и, хотя нашел некоторую соответствующую информацию,

Вот что я нашел:

, но ни один из них не ответил удовлетворительно на вопрос.

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

Итак: теперь, когда наступил 2012 год, естьспособ сделать это еще, без компиляции AOT?Если так, пожалуйста, просветите меня!

Ответы [ 3 ]

2 голосов
/ 27 января 2012

Я предполагаю, что запускается как скрипт Вы имеете в виду через clojure.main следующее:

java -cp clojure.jar clojure.main /path/to/myscript.clj

Если это так, то существует простая техника: поместите все функции библиотеки в отдельное пространство имен, например mylibrary.clj Тогда myscript.clj может использовать / требовать эту библиотеку, как и ваш другой код. Но определенные функции в myscript.clj будут вызываться только при запуске в виде скрипта.

В качестве бонуса, это также дает вам хорошую структуру проекта, так как вы не хотите, чтобы специфичный для скрипта код смешивался с вашими общими функциями библиотеки.

РЕДАКТИРОВАТЬ:

Я не думаю, что в самом Clojure есть надежный способ определить, был ли отдельный файл запущен как сценарий или загружен как библиотека - с точки зрения Clojure, между ними нет 1015 * различий (все загружается одинаково через Компилятор .load (...) в исходном коде Clojure для всех, кто заинтересован).

Параметры, если вы действительно хотите определить способ запуска:

  • Напишите основной класс на Java, который устанавливает статический флаг, а затем запускает скрипт Clojure. Вы можете легко проверить этот флаг из Clojure.
  • Использование компиляции AOT для реализации основного класса Clojure, который устанавливает флаг
  • Используйте * аргументы командной строки *, чтобы указать использование скрипта. Вам нужно будет передать дополнительный параметр, например «script», в командной строке.
  • Использование метода, определяемого платформой, для определения командной строки (например, из переменных среды в Windows)
  • Используйте параметр --eval в командной строке clojure.main , чтобы загрузить файл clj и запустить специальную функцию, которая представляет ваш скрипт. Затем эта функция может установить специфичный для скрипта флаг, если необходимо
  • Используйте один из методов для определения основного класса Java во время выполнения
1 голос
/ 02 сентября 2013

Это может быть полезно: проект github lein-oneoff описывает себя как "управление зависимостями для одноразовых, однофайловых программ clojure."

Это позволяет вам определять все водин файл, но вам нужно установить плагин oneoff, чтобы запустить его из командной строки.

1 голос
/ 29 января 2012

Я придумала подход, который, хотя и глубоко ошибочен, кажется, работает.

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

Конечно, это очень хакерский и хрупкий, но, похоже, он работает:

(defn running-as-script
    "This is hacky and brittle but it seems to work. I’d love a better
    way to do this; see http://stackoverflow.com/q/9027265"
    []
    (let
        [known-namespaces
            #{"clojure.set"
                "user"
                "clojure.main" 
                "clj-time.format" 
                "clojure.core" 
                "rollup" 
                "clj-time.core" 
                "clojure.java.io" 
                "clojure.string" 
                "clojure.core.protocols"}]
        (= (count (all-ns)) (count known-namespaces))))
...