На прошлой неделе решил наконец ознакомиться с ClojureScript по-подробнее. До этого я смотрел презентацию Рича Хикки и некоторые другие скринкасты, успел "пощупать" ClojureScriptOne и почитать пару статей о том, как он (ClojureScript) крут. В общем, никаких особых сложностей с ним я не ожидал, поэтому начавшиеся приключения стали для меня откровенным сюрпризом.
Во-первых, мне не удалось создать browser-connected repl, соединенный со своей html-иной. Я выполнял простые туториалы шаг за шагом, и на этапе соединения у меня ничего не получалось. Тогда я запустил проект samples/repl, входящий в поставку ClojureScript. И все было хорошо до тех пор, пока я не попытался соединиться с веб-страницей. В результате, при помощи Дэвида Нолена и еще нескольких разработчиков ClojureScript выяснилось, что документация чуть-чуть не соответствует. После моих гневных отзывов её (документацию) наконец поправили, а я напишу здесь русский вариант туториала о том, как начать работать с ClojureScript.
1. Качаем с гитхаба последнюю версию ClojureScript.
2. Настраиваем emacs:
a) Создаем файл browser-repl.sh с правами на выполнение:
#!/bin/sh
if [ "$CLOJURESCRIPT_HOME" = "" ]; then
CLOJURESCRIPT_HOME="`dirname $0`/.."
fi
CLJSC_CP=''
for next in lib/: lib/*: src/clj: src/cljs: test/cljs; do
CLJSC_CP=$CLJSC_CP$CLOJURESCRIPT_HOME'/'$next
done
java -server -cp $CLJSC_CP clojure.main -e \
"(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)"
б) Прописываем в .emacs настройки для inferior-lisp'a:
(setq inferior-lisp-program "~/clojure/clojurescript/browser-repl.sh")
Здесь "~/clojure/clojurescript/browser-repl.sh" -- естственно, путь к созданному на шаге 2а файлу browser-repl.sh.
3. Добавляем clojurescript/bin в $PATH.
4. Заходим в каталог clojurescript/samples/repl, компилируем исходники: cljsc src/ > main.js
Файл main.js будет позднее использоваться в index.html
Обратите внимание на содержимое файла test.cljs. Он содержит такую строчку:
(repl/connect "http://localhost:9000/repl")
Именно она позволяет затем соединиться с Emacs-ом.
5. Файлы index.html, main.js и каталог out необходимо захостить на каком-нибудь веб-сервере. Я, например, просто создал каталог Tomcat7/webapps/my и сложил туда все это барахло. В моем случае страница index.html стала доступна по адресу localhost:8080/my/index.html.
Внимание! Хостить страницу обяхательно, просто открыв её как файл с диска вы не сможете к ней подконнектиться из Emacs-а!
6. Запускаем Emacs, выполняем команду M-x inferior-lisp.
7. Вводим следующие команды:
(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)
8. Загружаем/обновляем index.html в броузере. После этого repl в Emacs-е должен заработать. Например, вычисление (+ 1 1) должно выдать ответ 2. Если это произошло -- вуаля! у вас веб-консоль прямо в Emacs-е!
В моем примере index.html содержит следующий фрагмент:
Вообще, документация на ClojureScript достаточно бедная. Поэтому, вместо того, чтобы искать блог-посты и туториалы по использованию ClojureScript, я просто стал читать его исходники. Рекомендую для этого воспользоваться инструментом Marginalia. С Leiningen 2 это вообще просто.
1. В .lein/profiles.clj добавьте плагин lein-marginalia
{:user {:plugins [ [lein-marginalia "0.7.0"]
[lein-pprint "1.1.1"]
[lein-swank "1.4.4"]]}}
2. Создайте новый проект: lein new clj-docs
3. Скопируйте в катлог cljs-docs/src содержимое каталогоа cljorescript/src.
4. Выполните команду lein marg, и в каталоге docs будет создан файл uberdoc.html, который слева содержит комментарии к исходнику, а справа -- сам исходник.
Еще стоит ознакомиться с Google Closure API -- тоже полезное подспорье в работе с ClojureScript.
Ну а в целом, ClojureScript мне очень понравился, и я надеюсь использовать его дальше в своих проектах.
Во-первых, мне не удалось создать browser-connected repl, соединенный со своей html-иной. Я выполнял простые туториалы шаг за шагом, и на этапе соединения у меня ничего не получалось. Тогда я запустил проект samples/repl, входящий в поставку ClojureScript. И все было хорошо до тех пор, пока я не попытался соединиться с веб-страницей. В результате, при помощи Дэвида Нолена и еще нескольких разработчиков ClojureScript выяснилось, что документация чуть-чуть не соответствует. После моих гневных отзывов её (документацию) наконец поправили, а я напишу здесь русский вариант туториала о том, как начать работать с ClojureScript.
1. Качаем с гитхаба последнюю версию ClojureScript.
2. Настраиваем emacs:
a) Создаем файл browser-repl.sh с правами на выполнение:
#!/bin/sh
if [ "$CLOJURESCRIPT_HOME" = "" ]; then
CLOJURESCRIPT_HOME="`dirname $0`/.."
fi
CLJSC_CP=''
for next in lib/: lib/*: src/clj: src/cljs: test/cljs; do
CLJSC_CP=$CLJSC_CP$CLOJURESCRIPT_HOME'/'$next
done
java -server -cp $CLJSC_CP clojure.main -e \
"(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)"
б) Прописываем в .emacs настройки для inferior-lisp'a:
(setq inferior-lisp-program "~/clojure/clojurescript/browser-repl.sh")
Здесь "~/clojure/clojurescript/browser-repl.sh" -- естственно, путь к созданному на шаге 2а файлу browser-repl.sh.
3. Добавляем clojurescript/bin в $PATH.
4. Заходим в каталог clojurescript/samples/repl, компилируем исходники: cljsc src/ > main.js
Файл main.js будет позднее использоваться в index.html
Обратите внимание на содержимое файла test.cljs. Он содержит такую строчку:
(repl/connect "http://localhost:9000/repl")
Именно она позволяет затем соединиться с Emacs-ом.
5. Файлы index.html, main.js и каталог out необходимо захостить на каком-нибудь веб-сервере. Я, например, просто создал каталог Tomcat7/webapps/my и сложил туда все это барахло. В моем случае страница index.html стала доступна по адресу localhost:8080/my/index.html.
Внимание! Хостить страницу обяхательно, просто открыв её как файл с диска вы не сможете к ней подконнектиться из Emacs-а!
6. Запускаем Emacs, выполняем команду M-x inferior-lisp.
7. Вводим следующие команды:
(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)
8. Загружаем/обновляем index.html в броузере. После этого repl в Emacs-е должен заработать. Например, вычисление (+ 1 1) должно выдать ответ 2. Если это произошло -- вуаля! у вас веб-консоль прямо в Emacs-е!
В моем примере index.html содержит следующий фрагмент:
<div id="dates"> <div>23.05.2012</div> <div>25.05.2012</div> <div>27.05.2012</div> <div>28.05.2012</div> <div>29.05.2012</div> </div>
Таким образом, команды на скриншоте изменяют размер шрифта и цвет текста первой даты.
Вообще, документация на ClojureScript достаточно бедная. Поэтому, вместо того, чтобы искать блог-посты и туториалы по использованию ClojureScript, я просто стал читать его исходники. Рекомендую для этого воспользоваться инструментом Marginalia. С Leiningen 2 это вообще просто.
1. В .lein/profiles.clj добавьте плагин lein-marginalia
{:user {:plugins [ [lein-marginalia "0.7.0"]
[lein-pprint "1.1.1"]
[lein-swank "1.4.4"]]}}
2. Создайте новый проект: lein new clj-docs
3. Скопируйте в катлог cljs-docs/src содержимое каталогоа cljorescript/src.
4. Выполните команду lein marg, и в каталоге docs будет создан файл uberdoc.html, который слева содержит комментарии к исходнику, а справа -- сам исходник.
Еще стоит ознакомиться с Google Closure API -- тоже полезное подспорье в работе с ClojureScript.
Ну а в целом, ClojureScript мне очень понравился, и я надеюсь использовать его дальше в своих проектах.
Это вы еще километровых трейсов на пустом месте не видели. У меня совершенно противоположные ощущения от недели использования cljs, да -- проект интересный, но жутко сырой, в частности содержательность ошибок как времени компиляции, так времени выполнения (уже в браузере) стремится к нулю. 'Cannot call method call of undefined'.
ОтветитьУдалитьВообще, содержательность стектрейсов -- это больная тема всего Clojure, а не только ClojureScript. Лично я с этим никак не борюсь, просто пользую swank и slime, что позволяет мне писать программу достаточно небольшими фрагментами. Надеюсь, в ClojureScript эта методика тоже прокатит...
ОтветитьУдалитьUnknow, проект конечно сырой, но это потому, что это еще альфа-версия, разработка идет полным ходом.
ОтветитьУдалитьDmitry, интересно, почему вы не использовали lein-cljsbuild? С ним, кажется, настроить минимальное рабочее окружение гораздо проще.
Да, кстати, от стектрейсов хорошо помогает https://github.com/dnaumov/clojure-contracts ;)
Вначале хотел разобраться с нуля, как пользоваться ClojureScript, без посторонних инструментов.
ОтветитьУдалитьКстати, а чем тебе :pre и :post -кондишены не угодили, что аж целый фреймворк контрактов решил пилить?
Блин, комментарий куда-то пропал.
ОтветитьУдалить> Вначале хотел разобраться с нуля, как пользоваться ClojureScript, без посторонних инструментов.
Тогда понятно. Ну, надеюсь в скором времени запилят нормальную поддержку clojurescript в слайме - вот тогда будет красота.
> Кстати, а чем тебе :pre и :post -кондишены не угодили, что аж целый фреймворк контрактов решил пилить?
Во-первых, сообщения об ошибках у :pre\:post на редкость неинформативны (совершенно непонятно, что именно и почему упало), а во-вторых, они очень ограничены в возможностях (нельзя задавать их отдельно от определения функции, нет инвариантов и т.п.). Кроме того, использование функций вместо сырых sexpr'ов, на мой взгляд, делает код более лаконичным.
"Поподробнее" пишется слитно.
ОтветитьУдалить