我知道这个标题有很多问题,但是我无法从他们那里收集到答案,所以就这样了。
我是一名经验丰富的程序员,但对Clojure来说还算新手。我试图通过将RTF文件转换为HTML文件然后调用html解析器来解析它。
我正在使用的转换器(unrtf)总是打印到stdout,所以我需要捕获输出并自己编写文件。
(defn parse-rtf "Use unrtf to parse a rtf file" [#^java.io.InputStream istream charset] (let [rtffile (File/createTempFile "parse" ".rtf" (File. "/vault/tmp/")) htmlfile (File/createTempFile "parse" ".ohtml" (File. "/vault/tmp/")) command (str "/usr/bin/unrtf " (.getPath rtffile) ) ] (try (with-open [rtfout (FileOutputStream. rtffile)] (IOUtils/copy istream rtfout)) (let [ proc (.exec (Runtime/getRuntime) command) ostream (.getInputStream proc) result (.waitFor proc)] (if (> result 0) ( (println "unrtf failed" command result) ; throwing an exception causes a parse failure to be logged (throw (Exception. (str "RTF to HTML conversion failed"))) ) ( (with-open [htmlout (FileOutputStream. htmlfile)] (IOUtils/copy ostream htmlout)) ; since we now have html, run it through the html parser (parse-html (FileInputStream. htmlfile) charset) ) ) ) (finally (.delete rtffile) (.delete htmlfile) ) )))
异常指向
行(IOUtils/copy ostream htmlout))
这真让我感到困惑,因为我之前使用过那种形式(就在尝试之后:),似乎没关系。我看不出差异。
感谢您提供任何帮助。
答案 0 :(得分:4)
正如其他人正确指出的那样,您不能只为代码组织添加额外的括号来将表单组合在一起。 Clojure文件中的括号是用于分隔相应代码中的列表的标记;列表被计算为s表达式 - 也就是说,第一个表单被计算并且结果作为函数被调用(除非它命名一个特殊形式,如if
或let
)。
在这种情况下,您有以下内容:
(
(with-open [htmlout (FileOutputStream. htmlfile)]
(IOUtils/copy ostream htmlout))
; since we now have html, run it through the html parser
(parse-html (FileInputStream. htmlfile) charset)
)
IOUtils/copy
函数具有整数返回值(复制的字节数)。然后在评估周围的with-open
宏时返回此值。由于with-open
形式是列表中的第一个,因此Clojure将尝试从IOUtils/copy
调用整数返回值作为函数,从而导致您看到异常。
要评估多种形式的副作用而不调用第一种形式的结果,请将它们换成do
形式;这是一种特殊形式,用于计算每个表达式并返回最终表达式的结果,从而丢弃所有其他表达式的结果。许多核心宏和特殊表单(例如let
,when
和with-open
(以及许多其他表单)接受多个表达式并在隐式do
中对其进行评估。
答案 1 :(得分:2)
我没有尝试运行您的代码,只是看了一眼,在if (> result 0)
后((println ...)(throw ...))
没有do。有一个额外的parens会导致内部parens返回的值被视为一个函数并被执行。
尝试包含它,例如(do (println ...) (throw ...))