Clojure 反射警告 - 无法解决写入调用

joe*_*mct 3 java clojure

我正在努力获得正确的类型提示,以避免在从数据库查询写入文本文件输出时出现反射警告。

我试图在调用每个函数之前放置 ^String 类型提示,因为最终输出将命中磁盘上的文本文件。

反射警告发生在函数末尾的 :row-fn 行上。我Reflection warning, dbdump/dbdump.clj:157:44 - call to write can't be resolved.在同一行有评论。

我怎样才能摆脱这个警告?我认为在处理大型数据集时会产生性能成本。

(defn run-job [job-time-string db-spec config]
  (let [; {{{
        source-sql          (str "select * from " (:source-base-name config)(:table-name config))
        max-rows            (:max-rows            config)
        fetch-size          (:fetch-size          config)
        working-dir         (:working-dir         config)
        output-name           (str working-dir "/" job-time-string ".pipe" )
        field-delim         (:field-delim         config)
        row-delim           (:row-delim           config)
        log-report-interval (:log-report-interval config)
        row-count           (atom 0)  ; For state on rows
        db-connection       (doto (j/get-connection db-spec))
        statement           (j/prepare-statement db-connection source-sql :fetch-size fetch-size :concurrency :read-only :max-rows max-rows)
        start-in-millis     (System/currentTimeMillis)
        replace-newline (^String fn [s]
                          (if
                              (string? s)
                            (clojure.string/replace  s #"\n" " ")
                            s)) ; I'd prefer not to do this; Right now we can't load \n fields.
        row-fn          (^String fn [v]
                          (swap! row-count inc)
                          (when
                              (zero?
                               (mod @row-count log-report-interval))
                            (write-logs @row-count start-in-millis 3 (:table-name config) ))
                          (str (join field-delim (doall (map #(replace-newline %) v))) row-delim ))
        ]; }}}
    (with-open [^java.io.Writer wrtr (io/writer output-name )]
        (info "Fetching jdbc query..." )
        (info source-sql)
        (try
          (j/query db-connection [statement]
                   :as-arrays?    true
                   :result-set-fn vec
; Reflection warning, dbdump/dbdump.clj:157:44 - call to write can not be resolved.
                   :row-fn        ^String #(.write wrtr (row-fn %)))
          (catch Exception e
            (error (str "Error while fetching JDBC data." (.getMessage e)))
            (System/exit 9))))
    (write-logs @row-count start-in-millis 0 (str (:source-base-name config)  (:table-name config) " Completed - "))))
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyk 7

反射警告告诉您,您需要明确write要在 中调用哪个方法#(.write wrtr (row-fn %))。所以你需要输入提示wrtr(row-fn %)

#(.write ^java.io.Writer wrtr ^String (row-fn %))
Run Code Online (Sandbox Code Playgroud)

顺便说一下,向fn表单或函数文字添加类型提示没有任何效果。(好吧,添加原始提示确实会使结果函数实现相关clojure.lang.IFn$[OLD]+接口,但这些提示需要附加到参数向量和/或命名参数的各个符号。)

(相比之下,向defn表单中的函数名称添加类型提示确实会在结果变量上放置:tag元数据;这将被编译器用来消除 Java 方法调用的歧义。)