问题
我正在尝试使用Clojure定义一个类似于Java中try的宏。 它应该能够具有绑定形式,例如[变量 值],可以绑定到可关闭实例。
Java示例
try (Socket s = new Socket()) {
s.accept();
} catch(Exception e) {}
在这段代码中,套接字's'会自动关闭,就好像有一个显式的finally子句一样。
finally {
if (s != null) s.close();
}
尝试的解决方案
;I am defining my macro. It can either take one argument(expression) or can take two arguments(expression and a vector with two elements(a variable and value)
;expression is a form expression and should be able to be evaluated
(defmacro safe
; if a vector and also an expression is passed into the macro
[s NewS expression]
;I am defining my try block, and unquoting it with a ' so that the try block is not executed within the macro
`(try
;I am letting the variable(NewS) be equal to the value(s)
(let [s NewS]
;I am trying the expression to see if it is valid and printing the exception if there is one
(try
~expression (catch Exception e (str "caught exception: " (.getMessage e))))
)
;I am checking if my value is an instance of a java closeable
(instance? java.util.Closeable s)
;I am catching the exception from the let statement if there is one
(catch Exception e (str "caught exception: " (.getMessage e)))
)
;if only an expression is passed into the macro
[expression]
`(try
~expression (catch Exception e (str "caught exception: " (.getMessage e)))
)
)
示例输入和输出
user> (def v (safe (/ 1 0)))
user> v
#<ArithmeticException java.lang.ArithmeticException: Divide by zero>
user> (def v (safe (/ 10 2)))
user> v
5
user> (def v (safe [s (FileReader. (File. "file.txt"))] (.read s)))
user> v
105 ; first byte of file file.txt
user> (def v (safe [s (FileReader. (File. "missing-file"))] (. s read)))
user> v
#<FileNotFoundException java.io.FileNotFoundException:
missing-file (No such file or directory)>
错误信息
当我把这些示例输入放入我的主函数中时,我遇到了一个编译器异常,我不理解。
CompilerException clojure.lang.ArityException: Wrong number of args (1) passed to: core/safe, compiling:(/private/var/folders/6f/q7lhngtn45q_xpzd_24gjp2h0000gn/T/form-init2350735096437822603.clj:1:8)
我不知道我能在这个宏中调整什么,但我无法使其不返回错误。
更新
这个解决方案几乎有效。
(defmacro safe
([[s NewS] expression]
`(try
(let [~s ~NewS] ~expression) (catch Exception e# (str "caught exception: " (.getMessage e#)))
))
([expression]
`(try
~expression (catch Exception e# (str "caught exception: " (.getMessage e#)))
))
)
但是以下测试失败了
(defn -main "我还没有做很多事情..." [& args] (import java.io.FileReader java.io.File) (def v (safe [s (FileReader. (File. "file.txt"))] (.read s))) (println v) )
(注:该段代码为Clojure语言)
user$ lein run
caught exception: file.txt (No such file or directory)
user$ cat file.txt
teast
with-open
来完成这个任务。 - Taylor Wood(defmacro safe [& [s newS] expression] (if s `(let [~s ~newS])) `(with-open ~newS & ~expression) ) (defn -main [& args] (def v (safe (/ 1 0))) )
- Sammacroexpand
后的结果吗?你在这里的代码格式很差,所以很难阅读。 - Carcigenicates
和newS
的作用。 - Carcigenicate