Clojure макрос, который пишет блоки try

Jacob спросил: 14 ноября 2017 в 07:15 в: clojure

Я пытаюсь определить макрос, используя Clojure, который работает аналогично, чтобы попытаться в javaIt. Он должен иметь форму привязки, например, [значение переменной], которая может связываться с экземпляром закрываемого объекта.

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] (импорт java.io.FileReader java.io.File) (def v (safe [s (FileReader. ( Файл."File.txt"))] (.read s))) (println v))

user$ lein run
caught exception: file.txt (No such file or directory)
user$ cat file.txt 
teast

0 ответов