【问题标题】:Clojure giving reflection warnings depsite type hintsClojure 给出反射警告而不是类型提示
【发布时间】:2017-04-22 18:18:40
【问题描述】:

我正在编写一个聊天客户端/服务器,并且具有以下代码,该代码接受一个套接字,并返回一个 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))

给予:

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).

不过,我不知道如何才能使它更清楚。 p-outmessage 都被明确暗示。奇怪的是,拨打flush 没问题。

我该如何解决这个问题?

【问题讨论】:

    标签: clojure type-hinting


    【解决方案1】:

    问题在于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))
    

    【讨论】:

    • 哦!甚至没有想到这一点。接得好!那时就必须这样做。谢谢。
    猜你喜欢
    • 2011-06-06
    • 2020-02-18
    • 2019-11-25
    • 1970-01-01
    • 2019-05-27
    • 2019-10-18
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多