Clojure给出反射警告depsite类型提示

Car*_*ate 3 clojure type-hinting

我正在编写一个聊天客户端/服务器,并且具有以下带有套接字的代码,并返回一个可以用来更容易地写入套接字的clojure.core.async/channel.

我的问题是,尽管是类型提示,我仍然得到反映警告,呼叫.write无法解决.

(ns chat.main
  (:require [clojure.core.async :as a :refer [>! >!! <! <!! go thread chan]])

  (:import [java.net Socket ServerSocket]
           [java.io InputStream BufferedReader InputStreamReader OutputStream BufferedOutputStream PrintWriter]))

(set! *warn-on-reflection* true)

(defn new-output-chan [^Socket sock]
  (let [^OutputStream out (.getOutputStream sock)
        ^PrintWriter p-out (PrintWriter. out)
        out-chan (chan)]
    (go
      (while (.isConnected sock)
        (let [^String message (<! out-chan)]
          (.write p-out message) ; <---------- Here
          (.flush p-out)))
      (a/close! out-chan))
    out-chan))
Run Code Online (Sandbox Code Playgroud)

得到:

Reflection warning, C:\Users\slomi\IdeaProjects\chat\src\chat\main.clj:44:5 - call to method write on java.io.PrintWriter can't be resolved (argument types: unknown).
Run Code Online (Sandbox Code Playgroud)

我不知道怎么能让它更清楚.双方p-outmessage明确暗示.奇怪的是,这个电话flush很好.

我该如何解决这个问题?

Bey*_*mor 6

问题是go实际上将您的代码重写为状态机(您可以检查转换macroexpand-1,但结果非常冗长,所以我没有在此处包含它).不幸的是,看起来这种转换不会保留类型提示.

也许有一个更好的解决方案,但是如果你将调用拉出到它自己的函数中,你可以输入提示,因为它不会被以下内容重写go:

(defn new-output-chan [^Socket sock]
  (let [^OutputStream out (.getOutputStream sock)
        ^PrintWriter p-out (PrintWriter. out)
        out-chan (chan)
        write #(.write p-out ^String %)]
    (go
      (while (.isConnected sock)
        (let [message (<! out-chan)]
          (write message)
          (.flush p-out)))
      (a/close! out-chan))
    out-chan))
Run Code Online (Sandbox Code Playgroud)