2

関数値でリーダーを使用する方法はありますか。

(読み取り文字列 (pr-str +))

clojure.lang.Util.runtimeException から読み取れない (Util.java:219)

?

4

2 に答える 2

3

(pr-str +)読者が解析できる有効な Clojure コードではないため、出力は既にご存じかもしれません: "#<core$_PLUS_ clojure.core$_PLUS_@ff4805>". pr関数、prnなどを使用するときの関数値の出力は、表示されている例外をスローする にディスパッチするリーダー マクロにprintln意図的にラップされます。#<UnreadableReader

print-dup提供した例では、基本的なシリアル化に機能する関数を使用できます。

(defn string-fn [f]
  (let [w    (java.io.StringWriter.)]
    (print-dup f w)
    (str w)))

(let [plus (read-string (string-fn +))]
  (plus 1 2))

関数に対して行われたシリアル化+は、実際にはクラスのコンストラクターへの呼び出しを生成しています。

#=(clojure.core$_PLUS_. )

これはもちろん、文字列を読み取る Clojure 環境でクラスが既にコンパイルされている場合にのみ機能します。匿名関数をシリアライズし、ファイルに保存してから再度読み込んだ場合、新しい REPL セッションを実行すると、各匿名関数のクラス名が異なり、Clojure 内部に依存するため、おそらく機能しません。

任意の関数の場合、事態はさらに複雑になります。ソースコードを共有するだけでは不十分な場合があります。関数は、ソース環境にのみ存在する任意の数の他の関数または変数の使用に依存する可能性があります。これがあなたが考えていることである場合、おそらく解決しようとしている問題への他のアプローチを検討すると、任意の関数の値をシリアル化する必要がなくなります。

それが役に立てば幸い、

于 2013-06-23T19:52:33.880 に答える
0

名前だけが必要な場合は、(name '+) を使用してシンボルを送信できますか。

しかし、一般的に言えば、読み返したい場合に clojure read を使用することはお勧めできません。これは、clojure のリーダーがその過程で何らかのコードを実行する可能性があるためです。多分 edn リーダーを見てください: clojure.edn/read-string

しかし、文字列をシンボルに戻す必要があるだけかもしれません。その場合は、(シンボル名) 関数で十分です。

于 2013-06-23T20:17:49.917 に答える