Clojure:java.lang.Integer无法强制转换为clojure.lang.IFn

时间:2014-07-23 17:59:38

标签: clojure

我知道这个标题有很多问题,但是我无法从他们那里收集到答案,所以就这样了。

我是一名经验丰富的程序员,但对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))

这真让我感到困惑,因为我之前使用过那种形式(就在尝试之后:),似乎没关系。我看不出差异。

感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:4)

正如其他人正确指出的那样,您不能只为代码组织添加额外的括号来将表单组合在一起。 Clojure文件中的括号是用于分隔相应代码中的列表的标记;列表被计算为s表达式 - 也就是说,第一个表单被计算并且结果作为函数被调用(除非它命名一个特殊形式,如iflet)。

在这种情况下,您有以下内容:

(
  (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形式;这是一种特殊形式,用于计算每个表达式并返回最终表达式的结果,从而丢弃所有其他表达式的结果。许多核心宏和特殊表单(例如letwhenwith-open(以及许多其他表单)接受多个表达式并在隐式do中对其进行评估。

答案 1 :(得分:2)

我没有尝试运行您的代码,只是看了一眼,在if (> result 0)((println ...)(throw ...))没有do。有一个额外的parens会导致内部parens返回的值被视为一个函数并被执行。

尝试包含它,例如(do (println ...) (throw ...))