Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于写入try块的Clojure宏 问题_Clojure_Macros_Try Catch - Fatal编程技术网

用于写入try块的Clojure宏 问题

用于写入try块的Clojure宏 问题,clojure,macros,try-catch,Clojure,Macros,Try Catch,我正在尝试使用Clojure定义一个宏,其工作原理与java中的try类似 它应该能够有一个绑定表单,例如[variable value],可以绑定到closable的实例 Java中的示例 在这段代码中,套接字“s”被自动关闭,就好像有一个明确的finally子句一样 finally { if (s != null) s.close(); } 尝试解决方案 输入和输出示例 我不知道我可以在这个宏中调整什么,但我不能让它不返回错误 更新 这个解决方案几乎奏效 (defmacro safe

我正在尝试使用Clojure定义一个宏,其工作原理与java中的try类似 它应该能够有一个绑定表单,例如[variable value],可以绑定到closable的实例

Java中的示例 在这段代码中,套接字“s”被自动关闭,就好像有一个明确的finally子句一样

finally {
if (s != null) s.close();
}
尝试解决方案 输入和输出示例 我不知道我可以在这个宏中调整什么,但我不能让它不返回错误

更新 这个解决方案几乎奏效

(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.File.txt”))](.reads))) (打印版本五) )


自动关闭行为已通过使用open宏解决。参见实现。这里有一个公式(我认为)能满足你的要求

(defmacro safe
  ([body]
   `(try ~body
      (catch Exception e#
        (str "caught exception: " e#))))
  ([bindings & body]
   `(try
      (with-open ~bindings
        ~@body)
      (catch Exception e#
        (str "caught exception: " e#)))))
用法示例:

(safe (/ 1 nil))
;;=> "caught exception: java.lang.NullPointerException"

(safe [s (clojure.java.io/reader "file.txt")]
  (prn (.read s)))
;;=> "caught exception: java.io.FileNotFoundException: file.txt (No such file or directory)"

(spit "file.txt" "contents here")
(safe [s (clojure.java.io/reader "file.txt")]
  (.read s))
;;=> 99
然而
  • 失败时返回一个字符串是令人困惑的,因为如果期望值也是一个字符串呢?那么,您如何知道您的评估是成功还是失败?也许您只是想打印/记录异常并返回nil?(在这种情况下,考虑将<代码> STR <代码> > <代码> PRTLNN<代码>在您的代码> catch < /代码>块中)
  • 有两个
    safe
    (一个只采用一种主体形式,另一个采用绑定为
    close
    d和主体形式)的算术运算会纠缠应该分开的关注点<带有open的code>已经存在,当我们可以重用它时,我们不应该重新创建它
  • 这个版本的
    safe
    可以采用任意数量的表单,而不仅仅是一个表单,因此它现在更加灵活

    (defmacro safe
      [& body]
      `(try ~@body
         (catch Exception e#
           (println "caught exception:" (.getMessage e#)))))
    
    我们可以在
    safe
    中轻松使用
    和open
    来获得您想要的行为:

    (safe
     (prn (/ 1 2)) ;; prints 1/2
     (with-open [s (clojure.java.io/reader "not_a_file.txt")]
       (.read s))) ;; fails, prints exception
    
    (safe
     (with-open [s (clojure.java.io/reader "file.txt")]
       (char (.read s)))) ;; returns the first char from file we `spit` above
    ;;=> \c
    

    我想你可以用这个。我真的不明白我的主要缺点是什么。即使在使用open时,我也会遇到类似的错误
    (defmacro safe[&s newS]expression](如果s
    (let[~s~newS]))
    (使用open~newS&~expression))(defn-main[&args](def v(safe(/10)))
    您是否检查了
    macroexpand
    为您的宏提供的内容?这里的代码格式不好,因此很难阅读。此外,Clojure使用分号作为注释,而不是普通的哈希。另外,请思考一下
    s
    newS
    对于您的除法为0的示例是什么。
    user$ lein run
    caught exception: file.txt (No such file or directory)
    user$ cat file.txt 
    teast
    
    (defmacro safe
      ([body]
       `(try ~body
          (catch Exception e#
            (str "caught exception: " e#))))
      ([bindings & body]
       `(try
          (with-open ~bindings
            ~@body)
          (catch Exception e#
            (str "caught exception: " e#)))))
    
    (safe (/ 1 nil))
    ;;=> "caught exception: java.lang.NullPointerException"
    
    (safe [s (clojure.java.io/reader "file.txt")]
      (prn (.read s)))
    ;;=> "caught exception: java.io.FileNotFoundException: file.txt (No such file or directory)"
    
    (spit "file.txt" "contents here")
    (safe [s (clojure.java.io/reader "file.txt")]
      (.read s))
    ;;=> 99
    
    (defmacro safe
      [& body]
      `(try ~@body
         (catch Exception e#
           (println "caught exception:" (.getMessage e#)))))
    
    (safe
     (prn (/ 1 2)) ;; prints 1/2
     (with-open [s (clojure.java.io/reader "not_a_file.txt")]
       (.read s))) ;; fails, prints exception
    
    (safe
     (with-open [s (clojure.java.io/reader "file.txt")]
       (char (.read s)))) ;; returns the first char from file we `spit` above
    ;;=> \c