Как мне соединить исходный файл clojure с запущенным clojure repl в Emacs?

В настоящее время я добавляю функциональные возможности существующему веб-приложению J2EE в контейнере Tomcat и пишу свои дополнения с помощью Clojure. Моя установка проста: я просто добавляю вызовы статических методов, сгенерированных clojure, и кодирую всю тяжелую работу со стороны clojure. Процесс сборки заключается в компиляции кода закрытия (lein uberjar), а затем компиляции кода Java с этим jar-файлом в пути к классам.

В инициализации webapp у меня есть вызов сгенерированного класса, который запускает шикарный сервер с (swank/start-repl). Я хотел бы иметь возможность подключить мой слайм Aquamacs к этому серверу и работать с него в интерактивном режиме (до определенного момента я не буду пробовать ничего, что требует перекомпиляции на стороне Java). Но у меня есть ситуация, которую я не совсем понимаю. Если я сделаю \M-x slime-connect, я получаю приглашение REPL (после уведомления об отсутствии подчиненного процесса lisp, что я думаю, это нормально, поскольку подчиненный процесс lisp работает вне управления emacs). Я могу отлично оценивать формы и даже проверять такие вещи, как my.own.namespace/my-var. Однако, если я обращаюсь к файлу с уже скомпилированным кодом clojure, я не могу заставить слизь распознавать его как источник. Рассмотрим простой файл clojure:

(ns my.namespace
  (:gen-class
   :name my.namespace
   :methods [#^{:static true} [testFunc [] void]]))

(def *secret* "shhhh")

(defn -testFunc []
  (println (str "our secret is: " secret)))

Предполагая, что это было скомпилировано и включено в uberjar, загруженный веб-приложением, я могу оценить / проверить my.namespace/*secret*. Но если я попытаюсь выполнить eval внутри буфера кода, Slime подумает, что я нахожусь в пространстве имен user (что даже может иметь смысл!). Но теперь у меня остался один рабочий вариант - я должен оценить - одну за другой все формы в файле! \C-c \C-l (загрузка исходного файла) ничего не сделает - очевидно, просто возвращает nil и больше ничего не выводит. Компиляция всего, кажется, делает именно это - она ​​компилируется, показывает ошибки, если находит их, но не меняет мое пространство имен. И самым странным является \C-~ (пакет и каталог синхронизации), который, используя Common Lisp, делает именно то, что я хочу, но здесь он навсегда замораживает закрытый REPL.

Всегда есть возможность переключиться на REPL, набрать (in-ns 'my.namespace), и тогда все заработает правильно. Но это просто недостаточно практично, когда количество файлов clojure растет (поскольку пространство имен буфера кода не изменится автоматически!)

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


person Edgar Gonçalves    schedule 12.08.2010    source источник
comment
Цитируя вопрос: «Кажется, что компиляция всего и делает именно это - что вы имеете в виду?» То есть, какой метод загрузки кода Clojure вы имеете в виду, когда говорите о компиляции всего (код Clojure всегда компилируется, но вы, вероятно, имеете в виду какую-то функцию SLIME). Кроме того, какого именно результата вы ожидаете?   -  person Michał Marczyk    schedule 12.08.2010
comment
Компиляция всего - нажатие C-c C-k скомпилирует все формы в буфере файла в emacs, представит ошибки в этих формах и эффективно сделает динамически доступными переопределенные (и вновь определенные) формы (например, вызов webapp будет использовать этот недавно скомпилированный код). Извините за то, что не так ясно дал понять, как мог.   -  person Edgar Gonçalves    schedule 13.08.2010
comment
Я ожидал поведения, аналогичного тому, что я наблюдал при запуске SLIME с M-x swank-clojure-project: при переключении на файловый буфер пространство имен автоматически изменяется, поэтому при оценке чего-то там не будет использоваться пространство имен user. В качестве альтернативы, при компиляции / загрузке буфера с использованием _3 _ / _ 4_ следует оценивать все формы, включая начальный (ns ...), тем самым переключаясь на конкретное пространство имен и делая все последующие переменные принадлежащими ему. Разве это не ожидаемое поведение при стандартной настройке? (Я мог неправильно на это посмотреть ...)   -  person Edgar Gonçalves    schedule 13.08.2010


Ответы (3)


Возможно, я неправильно понимаю вашу проблему, но не можете ли вы (при посещении этого гипотетического буфера в emacs) нажать C-c C-k, чтобы скомпилировать буфер в вашем текущем экземпляре Clojure (к чему подключен Slime)?

Затем в буфере слизи переключитесь на это пространство имен с помощью (in-ns 'my.namespace). Тогда у вас должен быть доступ к тому, что вы скомпилировали в этом пространстве имен.

person Isaac    schedule 12.08.2010
comment
Хм, как я написал в комментарии к вопросу, эта компиляция будет работать, но я хочу сказать, что я привык, что (in-ns 'my.namespace) неявно следует после компиляции / загрузки файла. Это работало таким образом во всех реализациях Common Lisp, которые я использовал с SLIME, IIRC; Кроме того, необходимость вручную переключать пространства имен в 10 или более файловых проектах (особенно с более чем желательными перезапусками clojure) приводит к усталости - а вскоре и к безумию :) - поэтому, если я не делаю что-то неправильно, и взаимодействие я у меня должно быть так, я напишу обходной путь! - person Edgar Gonçalves; 13.08.2010
comment
Да, также, (in-ns 'my.namespace) вообще не работает, если оценивается на месте, в буфере файла .clj - я должен сделать это в REPL, тогда буфер этого файла переключает свое пространство имен. Для меня это тоже менее чем очевидно. - person Edgar Gonçalves; 13.08.2010
comment
Вы совершенно правы - это заноза в заднице. Думаю, я только что привык к этому и не программировал со Slime / Swank до Clojure. Дайте мне знать, если у вас появится работа! Я так понимаю, у тебя сейчас все работает? Есть ли что-то, на что еще нет ответа? (Не то чтобы я что-то ответил, но я хотел бы знать, могу ли я еще помочь!) - person Isaac; 13.08.2010
comment
Что ж, несмотря на то, что вы не полностью удовлетворены тем, как обстоят дела сейчас, вы ответили на мой вопрос - это не проблема с моей настройкой, это было нормальное поведение. Вот первая попытка обойти эту проблему: gist.github.com/522706 - все еще не работает делайте любое автоматическое обновление при переключении файлов, но добавьте сочетание клавиш к этой fn, и вы сэкономите время. Спасибо, Исаак! - person Edgar Gonçalves; 13.08.2010
comment
Спасибо за emacs fn - возможно, придется добавить его в .init. Однако может быть полезно не переключаться автоматически на пространство имен буфера, который вы только что оценили: если у вас нет: reload, установленного в импортируемой библиотеке, но вы вносите изменения в эту библиотеку, вам необходимо повторно -компилируйте его, но вы не захотите находиться в его пространстве имен. Так что значение по умолчанию имеет смысл, просто часто это неудобно. - person Isaac; 13.08.2010
comment
Хм, я должен усвоить это: трюк с перезагрузкой - в чем недостаток, активный монитор обновления файлов? Но я понимаю, что вы имеете в виду, и согласен - я оставлю это руководство. Я только что обобщил функцию fn, см. здесь. Он просто возвращается к C-c M-p, если нет пространства имен или если вы используете префикс. - person Edgar Gonçalves; 14.08.2010
comment
Я решил не принимать этот ответ - несмотря на то, что я создал полезную функцию (которую я все еще буду использовать), я нашел прямое решение проблемы, о которой я упомянул. Смотрите мой ответ. В любом случае спасибо, Исаак! - person Edgar Gonçalves; 21.08.2010

Автоматическое переключение пространств имен при компиляции никогда не было по умолчанию для swank-clojure, хотя это может быть дополнительная функция slime, которая работала с Clojure. Но C-c M-p для переключения ответа на пространство имен текущего буфера всегда работал у меня, и я никогда не слышал, чтобы у кого-то были проблемы с этим.

Вы используете последние стабильные версии clojure-mode и slime-repl? У вас установлен swank-clojure.el? (Вам это не нужно.) Похоже, это могло быть из-за несовпадения версий библиотек elisp. Если проблема не в этом, то это может быть ошибка Aquamacs; swank-clojure разработан для работы с GNU Emacs. Это также может быть ошибка слизи, если вы работаете из ствола, а не из последней версии elpa.

person Community    schedule 13.08.2010
comment
Пару часов назад я понял, что C-c M-p отлично работает на моей установке (Aquamacs, последняя стабильная версия clojure-mode и slime-repl, clojure-1.2-rc1). То, что продолжает висеть, - это C-c ~, но я предполагаю, что команда SLIME работает только для реализаций Common Lisp. Я ожидал, что сработает C-c C-l (загрузка) файла - я ожидал, что пространство имен изменится, но этого не произойдет! Для удобства будущих читателей функция, которую я набросал в gist.github.com/522706, также работает, но он не запрашивает пространство имен - он угадывает его из первой (ns ...) формы в буфере. - person Edgar Gonçalves; 13.08.2010

Я только что узнал, что удаление виновника этой проблемы: slime-redirect-inferior-output из slime-repl.el вызывалось из настроенного мною хука. Оказывается, он плохо работает без подчиненного-lisp-процесса (читай, шикарный сервер, запущенный из emacs).

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

person Edgar Gonçalves    schedule 21.08.2010