4

バックグラウンド

私はEmacsのハックを作成しました。これにより、ClojureフォームをエディターバッファーからREPLバッファーに送信できます。2つのバッファが異なる名前空間にある場合、コピーされたテキストは通常​​意味をなさないか、さらに悪いことに、意味をなすかもしれませんが、エディタバッファのテキストとは異なる意味を持つことを除いて、正常に機能しています。

REPLバッファーで意味をなすようにテキストを変換したいと思います。

CommonLispのソリューション

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の翻訳機能は何もしていません。これは、CommonLispとClojureのシンボルとパッケージ/名前空間の動作が異なるためです。

Common Lispでは、シンボルはパッケージに属し、シンボルのパッケージの決定は読み取り時に行われます。

Clojureでは、正当な理由により、シンボルは名前空間に属しておらず、シンボルの名前空間の決定は評価時に行われます。

これはClojureで実行できますか?

それで、最後に、私の質問:Clojureコードをある名前空間から別の名前空間に変換できますか?

4

2 に答える 2

1

(私自身の質問に答える...)

名前空間の外部から名前空間の非公開変数を参照するのは簡単ではないことを考えると、これを行う簡単な方法はありません。

http://christophermaier.name/blog/2011/04/30/not-so-private-clojure-functionsのアイデアに基づいて、おそらくハッキングが可能です。これには、フォームをウォークして、元のフォームで参照されている変数と同じ値を持つ新しい変数に解決される新しいシンボルを作成することが含まれます。おそらく私はこれをいつかさらに調査するでしょうが、今はそうではありません。

于 2013-03-09T10:55:21.910 に答える
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

于 2013-03-08T16:00:28.527 に答える