我想写:
(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替换when时也没有。
如果我完全删除时,该功能正常。
我想我不能在doto中使用 - 有没有很好的方法来写这个?
答案 0 :(得分:4)
(注意:这应该都有效,但我现在无法测试。请给它自己的理智检查。)
你可以写
(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
。
答案 1 :(得分:3)
我只想把它写成:
(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
方法,所以你不需要在任何意义上“完成”它在绑定向量中。
答案 2 :(得分:2)
(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)))
答案 3 :(得分:0)
您可以像这样将Descendants("table").LastOrDefault()
嵌套在cond->
内:
doto
哪个给您有条件的doto。