2

アップデート:

これまでご協力いただきありがとうございました。これは動作する私の新しいコードです。しかし、私が望んでいるようには正確ではありません。
Java 例外を返すために必要です (理由は聞かないでください)。例:

(safe (/ 1 0))
#<ArithmeticException java.lang.ArithmeticException: Divide by zero>

それが私が望む方法です。しかし、バインディングなどを処理するコードの他の節を使用すると、Clojure 例外が発生します。

(seefe [f(FileReader.(File. "C:/txtf.txt"))](. f read))
FileNotFoundException C:\txtf.txt (The system cannot find the file specified)  java.io.FileInputStream.open (:-2)

これを防ぎ、代わりに Java 例外を表示するにはどうすればよいですか?


(defmacro safe [bindings & code]
  (if (list? bindings)
    `(try 
      (println "line 8: try")
      ~bindings
      (catch Throwable e# e#))

  (if (= (count bindings) 0)
     `(try ~code
           (catch Throwable e# e#))
     `(let ~(subvec bindings 0 2)
                              (try
                                (safe ~(subvec bindings 2) ~@code)
                                (catch Throwable e# e#)
                                (finally
                                 (. ~(bindings 0) close)))))))

課題をやり遂げようとしていますが、個別指導なしでは不可能です。私の先生は、私たちが 1 週間で Clojure を独学し、この課題を完了することを期待しています。私のクラスのみんなは行き詰まっていて、もう先生が嫌いです。

さて、マクロはコードを試し、結果または例外を返すことができるはずです。次のような式を処理できるはずです。

(def v (safe [s (FileReader. (File. "file.txt"))] (. s read)))

コードがファイルストリームなどを開いた場合は、finally 句でそれらを閉じる必要があります。これは私がこれまでに得たものです-機能していないことに気づきました。

(defmacro safe [& body]
`(try ~@body 
 (catch Throwable e# e#)
 (finally 
   (if (. ~@body isInstance Closable) (. ~@body close)))))

私が得るエラーは次のとおりです。

シンボルを解決できません: このコンテキストで s をコンパイルしています:(NO_SOURCE_PATH:1)

私は必死になったので、さまざまなことをたくさん試しました。

to edit the macro:

(defmacro safe [& body]
`(try ~@body 
      (catch Throwable e# e#)
      (finally (if (. ~@body isInstance Closable) (. ~@body close)))))

次に実行します:

(safe (. (java.io.FileReader. (java.io.File. "C:/Users/Dyallo.L/Dropbox/DVK11/PROP/Clojure/txt.txt")) read))

その結果:

そのような変数はありません: clooj.cemerick.pomegranate/Closable、コンパイル:(NO_SOURCE_PATH:1)

誰かがマクロ WITH-OPEN について言及しましたが、それは私の一般的なマクロではうまく機能しないと思います。このマクロはファイルを開くためのものではありませんが、開いている場合は、間違いなくファイルを閉じる必要があります。

くそっ、手を貸してくれないか Stackoverflow-geniuss? 事前に感謝します。

4

2 に答える 2

2

with-openマクロはまったく同じことを行います。

作成されたオブジェクトにバインドされた変数 (複数の場合があります) がある場合、bodytotry-catchブロックをfinally閉じてラップします。

(macroexpand-1 '(with-open [f (FileReader. (File. "1.txt"))]
                  (do this with f)
                  (do that with f)))

=>
(clojure.core/let
 [f (FileReader. (File. "1.txt"))]
 (try (clojure.core/with-open []
        (do this with f)
        (do that with f))
      (finally (. f clojure.core/close))))

バインディングがない場合は、本体を返すだけです

(macroexpand-1 '(with-open []
                  (do this with f)
                  (do that with f)))

=>
(do (do this with f)
    (do that with f))

アップデート。アーサーは、あなたの質問の「例外」の部分をすでに説明しています。

于 2013-01-10T16:53:25.260 に答える
2

この例から、安全なマクロに渡される最初の形式は、名前式のペアのベクトルであり、[a (open-something "/foo/bar") b (oopen-something-else)]その後にこれらのシンボルを使用するいくつかの式が続くように見えます。代入を正しく解釈していれば、結果は with-open やさまざまな with-connection マクロと非常によく似たものになります。もちろん、結果を送信する前に、この仮定を再確認する価値があります。マクロが、その構造について少なくともある程度の知識なしに、その本体でクローズ可能な値を見つけることになっているとしたら、それははるかに困難です。

于 2013-01-10T17:06:19.510 に答える