Почему Clojure не может вывести этот тип определения?

Я писал тест клиент-сервер и столкнулся с чем-то неожиданным. В следующем коде аргумент порта 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или перед аргументом, но зачем это нужно? Разве не должно быть очевидно, что это за тип?

2 ответа

Решение

На самом деле невозможно определить тип значения, хранящегося в переменной в Clojure, потому что переменная может быть переопределена в любое время.

Однако у Clojure не должно быть проблем с определением типа во время выполнения, и, хотя для устранения неоднозначности во время выполнения потребуется использование отражения, соответствующий код должен (и должен) выполняться.

Кажется, ошибка связана с Cursive: /questions/7598085/kak-ustranit-neodnoznachnost-v-clojure/7598093#7598093

Добавление подсказки типа... для указания того, какую перегрузку вы ожидаете использовать, устранит необходимость в отражении и, возможно, успокоит 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)]))
Другие вопросы по тегам