Несоответствие запуску clojure jar из командной строки

У меня есть программа clojure, которая в какой-то момент выполняет функцию с именем db-rebuild-files-table. Эта функция принимает имя файла каталога в качестве одного строкового аргумента и вызывает рекурсивную функцию, которая спускается в дерево файлов каталога, извлекает определенные данные из находящихся там файлов и регистрирует каждый файл в базе данных mysql. Конечным результатом этой команды является таблица «файлы», заполненная всеми файлами в дереве в данном каталоге.

Мне нужно иметь возможность периодически запускать эту команду из оболочки.

Итак, я добавил директиву :gen-class в файл, содержащий мою функцию -main, которая на самом деле вызывает (db-rebuild-files-table *dirname*). Я запускаю lein uberjar и создаю банку, которую затем могу выполнить:

java -jar my-project-SNAPSHOT-1.0.0-standalone.jar namespace.containing.main

Разумеется, функция запускается, но в базе данных существует только одна запись для каталога *имя_каталога*. Когда я выполняю точное то же самое sexp в clojure REPL, я получаю правильное поведение: все дерево файлов под *dirname* обрабатывается.

Что я делаю неправильно? Почему вызов (db-rebuild-files-table *dirname*) ведет себя непоследовательно при вызове из REPL и при выполнении из командной строки?

[EDIT] Что еще более странно, так это то, что я нигде не получаю ошибок. Все вызовы функций работают как надо. Я даже могу запустить функцию -main в REPL, и она правильно обновляет таблицу.


person kliron    schedule 04.12.2011    source источник
comment
Какую версию Clojure вы используете?   -  person Scott    schedule 04.12.2011


Ответы (2)


Если это работает в REPL, но не при автономном выполнении, то я предполагаю, что вы можете быть укушены ленью Clojure.

Возможно, ваш код нуждается в doseq, чтобы получить преимущества побочного эффекта (например, запись в вашу базу данных)?

person Scott    schedule 04.12.2011
comment
Точно. Спасибо! Я написал свой ответ выше как раз перед тем, как вы опубликовали это. [РЕДАКТИРОВАТЬ] Для протокола: я перепишу свою реализацию с использованием дозыq, как вы предлагаете, поскольку дерево файлов может быть огромным, и нет необходимости хранить все это в памяти с помощью doall. - person kliron; 04.12.2011

Успешно справился. Это была очень коварная ошибка в моей программе. Меня укусила лень clojure. Моя функция файлового дерева использовала map для внутреннего использования и поэтому выдавала только первое значение — корневой каталог. По какой-то причине я до сих пор не могу понять, при выполнении в REPL оценка была фактически принудительной, и было создано целое дерево seq. Я только что добавил doall в свою функцию, и это решило ее.

Все еще пытаюсь понять, почему выполнение чего-то в REPL требует оценки. Есть предположения?

person kliron    schedule 04.12.2011
comment
REPL всегда печатает возвращаемое значение последнего переданного ему выражения, поэтому ему необходимо оценить последовательность, чтобы напечатать последнее выражение в качестве вывода. Напротив, это не относится к программе Clojure, работающей «нормально». Я постоянно попадаюсь на этом (но это имеет смысл)! - person Scott; 04.12.2011