背景
我已經寫了一個Emacs的黑客,讓我從編輯器緩衝區發送一個Clojure表單到一個REPL緩衝區。它工作的很好,除了如果兩個緩衝區位於不同的命名空間中,複製的文本通常沒有意義,或者更糟糕的是,它可能有意義,但與編輯器緩衝區中的意義不同。我可以將Clojure表單從一個包轉換爲另一個包嗎?
我想轉換文本,以便它在REPL緩衝區中有意義。
一種解決方案,Common Lisp的
Common Lisp中,我能做到這一點使用下面的功能:
;; Common Lisp
(defun translate-text-between-packages (text from-package to-package)
(let* ((*package* from-package)
(form (read-from-string text))
(*package* to-package))
(with-output-to-string (*standard-output*)
(pprint form))))
和樣品使用:
;; Common Lisp
(make-package 'editor-package)
(make-package 'repl-package)
(defvar repl-package::a)
(translate-text-between-packages "(+ repl-package::a b)"
(find-package 'editor-package)
(find-package 'repl-package))
;; => "(+ A EDITOR-PACKAGE::B)"
包名資格中輸入字符串和輸出字符串是不同的 - 正是需要解決在包之間複製和粘貼文本的問題。
(順便說一句,有關如何在Common Lisp過程中運行翻譯代碼並在Emacs世界和Common Lisp世界之間移動東西的東西,但是我對此很滿意,而且我並不特別想要到這裏)
一個無解Clojure中
這裏有一個直接翻譯成Clojure的:
;; Clojure
(defn translate-text-between-namespaces [text from-ns to-ns]
(let [*ns* from-ns
form (read-string text)
*ns* to-ns]
(with-out-str
(clojure.pprint/pprint form))))
和樣品使用:
;; Clojure
(create-ns 'editor-ns)
(create-ns 'repl-ns)
(translate-text-between-namespaces "(+ repl-ns/a b)"
(find-ns 'editor-ns)
(find-ns 'repl-ns))
;; => "(+ repl-ns/a b)"
所以Clojure中的翻譯功能什麼也沒做。這是因爲Common Lisp和Clojure中的符號和包/命名空間的工作方式不同。
In Common Lisp符號屬於一個包,符號包的確定發生在讀取時。
在Clojure中,出於很好的理由,符號不屬於名稱空間,符號名稱空間的確定發生在評估時間。
這可以在Clojure中完成嗎?
因此,最後,我的問題是:我可以將Clojure代碼從一個名稱空間轉換爲另一個名稱空間嗎?
你看過https://github.com/clojure/tools.reader了嗎? – sw1nn 2013-03-08 12:43:30
@ sw1nn:我剛剛看了一眼。我不認爲有什麼可以幫助的 - 沒有任何關於命名空間的東西。這是關於我認爲的符號分辨率,這是發生在評估時間,而不是閱讀時間。 – 2013-03-08 13:05:11
很困惑。爲什麼不對錶單進行評估 - 像nrepl這樣的工具會在正確的名稱空間中執行此操作,所以它一切正常。你想達到什麼結果?如果您想要交互式repl,那麼將當前REPL移動到當前緩衝區的命名空間也很容易。 – 2013-03-08 15:21:48