дото и установка свойства условно - PullRequest
3 голосов
/ 15 сентября 2010

Я хочу написать:

(defn download-web-page
    "Downloads the webpage at the given url and returns its contents."
    [^String url ^String user ^String password]
    (with-open [client (doto (WebClient.)
                       (when user (.set_Credentials (NetworkCredential. user password ""))))]
    (.DownloadString client url)))

Поэтому я хочу устанавливать учетные данные только тогда, когда они заданы в качестве аргумента функции. Однако, похоже, это не сработает - и то же самое не происходит, когда я заменяю if на if.

Функция работает нормально, если я удаляю, когда вообще.

Думаю, я не могу использовать, когда в doto - есть хорошие способы написать это?

Ответы [ 4 ]

4 голосов
/ 15 сентября 2010

(Примечание. Надеемся, что все это сработает, но я не могу проверить это в настоящее время. Пожалуйста, сделайте свою собственную проверку работоспособности.)

Вы могли бы написать

(defn download-web-page
  "Downloads the webpage at the given url and returns its contents."
  ([^String url] (download-web-page url nil nil))
  ([^String url ^String user ^String password]
     (with-open [client (doto (WebClient.)
                          (-> (.set_Credentials
                               (NetworkCredential. user password ""))
                              (->> (when user))))]
       (.DownloadString client url))))

Это кажется мне довольно запутанным. Другой подход:

(defn download-web-page
  "Downloads the webpage at the given url and returns its contents."
  ([^String url] (download-web-page url nil nil))
  ([^String url ^String user ^String password]
    (with-open [client (let [c (WebClient.)]
                         (when user
                           (.set_Credentials
                            (NetworkCredential. user password "")))
                         c)]
      (.DownloadString client url))))

Свернутый шаблон -> / ->> из первой версии можно абстрагировать с помощью макроса:

(defmacro doto-guard [guard action]
  `(-> ~action ~guard))

Тогда вы могли бы написать

(doto (WebClient.)
  (doto-guard (when user) (.setCredentials ...)))

Это имеет приятное свойство: вы можете использовать его несколько раз в одной форме doto, смешивая в обычных предложениях doto. В любом случае, хорошо, если подобные вещи встречаются в вашем коде чаще. В противном случае версия на основе let подойдет.

(Если этот шаблон подходит для действительно часто для вас, макрос можно сделать более гибким ... Также заманчиво сделать его немного менее гибким, но красивее, скажем заменив ~guard на (when ~guard), чтобы в момент использования можно было написать (doto-guard user (.setCredentials ...)). Однако любая серьезная причина выбора конкретной версии должна исходить из более широкого контекста.)

Разделение на два функциональных тела - это просто вопрос стиля - я предпочитаю не писать nil nil, когда учетные данные фактически не предоставлены.

3 голосов
/ 15 сентября 2010

Я бы просто написал это как:

(defn download-web-page
  "Downloads the webpage at the given url and returns its contents."
  [^String url ^String user ^String password]
  (with-open [client (WebClient.)]
    (when user
      (.set_Credentials client (NetworkCredential. user password "")))
    (.DownloadString client url)))

with-open не предъявляет особых требований к client, за исключением того, что у него есть метод close без аргументов, поэтому вам не нужно «заканчивать» его в каком-либо смысле в векторе привязок. 1007 *

2 голосов
/ 15 сентября 2010
(defn download-web-page
  "Downloads the webpage at the given url and returns its contents."
  [^String url ^String user ^String password]
  (let [client (WebClient.)]
    (when user 
      (.set_Credentials client (NetworkCredential. user password "")))
    (with-open [client client]
      (.DownloadString client url)))

(with-open [client client]... выглядит немного странно, но эй, это неприятный код с состоянием.Если этот условный параметр в doto встречается достаточно часто, он может оправдать макрос, но я сначала перейду к функции компоновщика:

(defn build-web-client
  [^String user ^String password]
  (let [client (WebClient.)]
    (when user 
      (.set_Credentials client (NetworkCredential. user password "")))
    client))

(defn download-web-page
  "Downloads the webpage at the given url and returns its contents."
  [^String url ^String user ^String password]
    (with-open [client (build-web-client user password)]
      (.DownloadString client url)))
0 голосов
/ 18 апреля 2019

Вы можете вкладывать cond-> внутрь doto примерно так:

(doto (java.util.Vector.)
  (cond-> (= 1 1) (.add "bla")))
;; => ["bla"]

(doto (java.util.Vector.)
  (cond-> (= 1 2) (.add "bla")))
;; => []

, что дает вам условное дото.

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