Начиная с Clojure без опыта Java - как лучше организовать и запустить проекты?
Извините заранее за несколько дискурсивный характер этой совокупности связанных вопросов; Я надеюсь, что ответы станут полезным ресурсом для новичков Clojure.
Я только начал изучать Clojure, частично мотивированный этот эссе. Я не профессиональный разработчик, но у меня есть несколько десятилетий опыта программирования (ARexx, VB/VBScript/VBA, а затем Perl и ежедневное использование R, начиная с 2011 года). Моя платформа - 64-битная Windows 7. Я использую Emacs 24.3, cider 20131221 и Leiningen 2.3.3 на Java 1.7.0_45 64-разрядном сервере Java Hotspot. Я купил Clojure Программирование и Clojure Анализ данных Cookbook и погрузился в оба. Я нашел их многообещающими, но я теряюсь в деталях.
Очевидно, что нужно сделать, чтобы застрять и экспериментировать с упражнениями кода и небольшими задачами, но непосредственной проблемой для меня была сложность структурирования, организации и даже простых запущенных проектов в Clojure. С R я могу уйти с файлом простого текста, содержащим основную часть кода, возможно, с одним или двумя другими, содержащими общие функции для больших проектов.
Clojure очень отличается и не имеет опыта работы на Java, я изо всех сил пытаюсь собрать эти штуки. Clojure В программировании есть целая глава по организации и строительству проектов, но она настолько всеобъемлющая, что, наоборот, мне трудно разоблачить информацию, имеющую отношение ко мне сейчас. Наверное, я искал что-то вроде этого ответа в Swank, но инструменты, похоже, с этого времени продвинулись. Так вот.
- Leiningen производит среди прочего файл
project.clj
, который содержит определение проекта и зависимости. Думаю, я понял. Могу ли я использовать этот файл для кода, не связанного с определением, ниже defproject
, или лучше оставить его нетронутым и иметь сам код в разных файлах clj
?
- Если ответ заключается в том, чтобы оставить только файл
project.clj
, как установить связь между этим и другими файлами? Просто ли все файлы clj
в папке проекта считаются частью проекта?
- Как определить основной файл кода, "точку входа" проекта? Скажем, у меня есть
project.clj
и main.clj
с некоторыми вспомогательными функциями в common.clj
- как определяются отношения между этими тремя файлами? Я могу вызывать функции из main.clj
, но как проект знает, что основной является ядром проекта, если/когда я упаковываю проект в uberjar?
- Если у меня есть несколько файлов
clj
, каков наилучший способ импорта функций? Я читал о require
и use
(и import
и refer
и...), но я не совсем понимаю разницу, и эти два ключевых слова трудно найти. Примеры для REPL в Clojure книге анализа данных чаще всего выбирают use
. Я нашел аналогичный вопрос, но это было немного над моей головой.
- Это больше зависит от конкретного инструмента, но по мере того, как Emacs, по-видимому, широко используется, кажется справедливым спросить: какой хороший рабочий процесс запускать небольшие фрагменты кода, указанные (скажем), пример
main.clj
, приведенный выше? В настоящее время я просто открываю файл main.clj
в Emacs, делаю M-x cider-jack-in
, чтобы установить REPL, эксперимент в REPL, а затем, когда я хочу попробовать что-то, я выбираю весь буфер и выбираю Eval region
из меню CIDER (C-c C-R
). Является ли эта стандартная процедура работы или совершенно ошибочной?
- Существует ли соглашение для определения пространств имен? Я думаю, я понимаю, что пространства имен могут охватывать несколько файлов
clj
и что ns
используется для определения пространства имен. Должен ли я явным образом определять пространство имен (в начале) каждого файла кода? Clojure Программирование имеет некоторые рекомендации, но меня интересуют данные от других пользователей.
- Clojure программирование говорит "Использовать символы подчеркивания в именах файлов, когда пространства имен содержат тире. Очень просто, если ваше пространство имен должно быть
com.my-project.foo
, исходный код для этого пространства имен должен находиться в файле, расположенном в com/my_project/foo.clj
". (EDIT, как объяснено в этот полезный ответ, а также этот). Это ограничение никогда бы не произошло со мной. Существуют ли какие-либо другие ошибки в отношении имен пространств имен и переменных? R часто использует точки в именах переменных, но, я думаю, учитывая соединение с Java, в большинстве случаев следует избегать точек.
Ответы
Ответ 1
- Нет, не указывайте фактический код там, если вы не знаете, что делаете (например, сгенерируйте номер версии для defproject из локального репозитория git, как в репозиториях juxt)
- Project.clj - это просто один большой параметр для инструмента Clojures build leiningen. См. Пример здесь https://github.com/technomancy/leiningen/blob/master/sample.project.clj. Например, вы можете указать другой исходный каталог, чем
src
в :source-path
.
- Значение по умолчанию -
-main
в project.core
, но вы можете указать различные конфигурации в project.clj
.
-
require
является предпочтительным. :use
импортирует все публики пространства имен, если вы не используете его в сочетании с :only
. Требовать, чтобы вы использовали псевдоним для всего пространства имен с :as
, но вы можете иметь тот же эффект от use
с помощью :only
, используя :refer
. Обратите внимание, что в ClojureScript :use
без :only
даже не разрешено.
- Это нормально. Есть и другие комбо, например.
C-c C-k
, чтобы перезагрузить весь файл буфера. Если вы входите слишком много форм в REPL и скорее отредактируете их в отдельном буфере https://www.refheap.com/22235.
- Мне нравится экспериментировать, пытаясь назвать пространства имен в глаголах, а не существительные, e. г. Я предпочитаю
myproject.parse
, myproject.interpret
, над myproject.parser
, myproject.interpreter
и т.д. Но это вопрос личного стиля. EDIT: Да, явное определение имен пространства имен по его имени файла и форме ns
в начале исходного файла. Необычно иметь несколько исходных файлов, определяющих одно пространство имен.
- Afaic это единственное предостережение относительно наименования пространства имен. Вы не можете это знать заранее.
Мне нравится ваш "беспокойный" подход. Вы (надеюсь) узнаете, что Clojure и особенно Leiningen почти бессмысленны в терминах этих вопросов.
Что касается использования REPL: я видел ваш комментарий в ответ @Mars, что вы хотите использовать REPL таким образом, чтобы вы могли повторно использовать то, что вы вводите. Две вещи:
- Динамическое развитие является удивительным, позволяя вам интерактивно протестировать небольшие компоненты или функции, без необходимости запускать всю программу, написанную для этой цели.
- Если вы обнаружите, что вы сами вводите огромные формы в REPL, которые вы намерены позже или позже перекомпоновать в функции или тесты, я рекомендую редактировать их в отдельном файле clj, который не является частью источника проекта (т.е. не в Пространство имен). Затем вы можете использовать this Emacs взломать формы eval из буфера Clojure в REPL. Идеально разделяйте Emacs в двух окнах (C-x 3) с помощью nrepl-буфера с одной стороны и вашего .clj с другой стороны. Затем используйте
C-x C-.
из файла clj, чтобы иметь форму в точке, вставленной в nrepl, и оцениваться. Инструкции по установке находятся по ссылке (и ваш файл .emacs обычно находится в домашнем каталоге).
Ответ 2
@Igrapenthin ответы велики. Вот еще несколько мыслей.
В пространствах имен этот учебник отлично.
Просто пояснить re # 2: Нет, не просто класть файлы .clj в любом месте проекта. Они должны находиться под src/или в любых каталогах (в виде строк) в векторе после :source-paths
в project.clj, если эта запись существует. Затем удалите этот исходный путь, когда вы создаете имена имен пространства имен. Это сводило меня с ума, пока я не понял это. (Люди, которые знают лучше, пожалуйста, поправьте меня, если что-то здесь не так.)
Один № 3, вам нужен ответ Igraphenthin, но почему бы просто не начать с оценки выражений в REPL? Я работаю над проектом в течение нескольких недель, и он делает много, но моя функция -main
все еще ничего не делает. Я просто запускаю те части, над которыми я работаю. Ну, вы привыкли к языкам с полнофункциональными подсказками - вы решаете.
РЕДАКТИРОВАТЬ. Независимо от того, используете ли вы функцию -main
для чего-либо, вы также можете поместить ключевые слова :use
или :require
в оператор ns
, который определяет пространство имен для того же файла. Они будут автоматически вызваны при запуске REPL с помощью lein repl
, и все, что вы сделали доступными с помощью ключевых слов ns
, будет доступно в REPL. Таким образом, у вас есть ваша предыдущая работа, но вы можете играть с ней по-разному в REPL. (Кроме того, если вам не нравится имя по умолчанию для автоматически загружаемого файла, вы можете переопределить его в project.clj с помощью :main
. Играфентин ссылался на это.)