为什么 Clojure 无法推断出这个 def 类型?

Why is Clojure unable to infer this def type?

我正在写一个 client/server 测试,运行 变成了意想不到的东西。在以下代码中,无法推断出 Socket 构造函数的端口参数:

(ns second-try.test.client
  (:import [java.net Socket]))

(def port 5555)

(defn -main []
  ; "Cannot disambiguate overloads of Socket"
  (let [sock (Socket. "127.0.0.1" port)]))

第一个参数的类型应该很明显,因为我传递的是文字。我认为端口的类型也很明显,因为它只是一个字面意思;尽管其中一个隐藏在 def.

后面

但出于某种原因,它无法确定 port 的类型。我可以通过在 def 或参数前面添加注释来补救它,但为什么这是必要的?类型是什么不应该很明显吗?

在 Clojure 中,实际上不可能推断出存储在 var 中的值的类型,因为 var 可以随时 re-defined。

但是,Clojure 在 run-time 处确定类型应该没有任何问题,尽管它需要使用反射来消除 run-time 处的歧义,但相关代码应该(并且确实如此) ) 运行.

该错误似乎与草书相关:

Adding a type-hint ... to specify which overload you expect to use would remove the need for reflection and hopefully calms Cursive down.

对于你的情况,我会尝试类似的方法:

(defn -main []
  ; "Cannot disambiguate overloads of Socket"
  (let [^int p port
        sock (Socket. "127.0.0.1" p)]))

在这种情况下,只需将您的 var 声明为 :const:

(def ^:const port 5555)

(defn -main []
  (let [sock (Socket. "127.0.0.1"  port)]))