2013-03-08 44 views
4

背景

我已經寫了一個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代碼從一個名稱空間轉換爲另一個名稱空間嗎?

+0

你看過https://github.com/clojure/tools.reader了嗎? – sw1nn 2013-03-08 12:43:30

+0

@ sw1nn:我剛剛看了一眼。我不認爲有什麼可以幫助的 - 沒有任何關於命名空間的東西。這是關於我認爲的符號分辨率,這是發生在評估時間,而不是閱讀時間。 – 2013-03-08 13:05:11

+0

很困惑。爲什麼不對錶單進行評估 - 像nrepl這樣的工具會在正確的名稱空間中執行此操作,所以它一切正常。你想達到什麼結果?如果您想要交互式repl,那麼將當前REPL移動到當前緩衝區的命名空間也很容易。 – 2013-03-08 15:21:48

回答

1

(回答我的問題...)

鑑於這並不容易從空間外面引用一個命名空間的非公開瓦爾,有沒有簡單的方法來做到這一點。

基於http://christophermaier.name/blog/2011/04/30/not-so-private-clojure-functions的想法,也許可能是黑客行爲。這將涉及走形式和創建新的符號,以解決與原始形式中提到的變量具有相同價值的新變量。也許我會在某個時候進一步調查,但現在不行。

+0

我決定寫一篇關於所有這些的博客文章,並最終討論了一些關於Clojure和Common Lisp中符號之間差異的內容。這是[這裏](http://nomistech.blogspot.co.uk/2013/03/symbols-and-namespaces-in-clojure-and_912.html)。 – 2013-03-26 16:54:55

1

我不明白你的用例,但是這裏有一種將符號從一個名字空間轉換爲另一個名字空間的方法。

(require 'clojure.walk 'clojure.pprint) 

(defn ns-trans-form [ns1 ns2 form] 
    (clojure.walk/prewalk 
    (fn [f] (if ((every-pred symbol? #(= (namespace %) ns1)) f) 
       (symbol ns2 (name f)) 
       f)) 
    form)) 

(defn ns-trans-text [ns1 ns2 text] 
    (with-out-str 
     (->> text 
      read-string 
      (ns-trans-form ns1 ns2) 
      clojure.pprint/pprint))) 

(print (ns-trans-text "editor-ns" "repl-ns" "(+ editor-ns/a b)")) 
;=> (+ repl-ns/a b) 

所以,editor-ns/a被轉化爲repl-ns/a

相關問題