2010-09-14 6 views
3

Je veux écrire:doto et réglage de la propriété conditionnelle

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

Je veux mettre les informations d'identification que lorsqu'ils sont donnés comme argument à la fonction. Cependant, il ne semble pas fonctionner de cette façon - et ne le fait pas quand je remplace le quand avec un si.

La fonction fonctionne correctement si je supprime le quand tout à fait.

Je suppose que je ne peux pas utiliser un quand dans un doto - y at-il de bons moyens d'écrire cela?

Répondre

3

Je voudrais juste écrire comme:

(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 n'impose pas de demandes particulières sur client, sauf qu'il a un non-arguments close méthode, de sorte que vous n'avez pas besoin de « terminer » il dans tous les sens au sein du vecteur de liaisons.

+1

je supposé de la façon dont il a été écrit que les informations d'identification nécessaires à fixer avant que la connexion soit ouverte. Votre code s'ouvre en premier, puis définit les informations d'identification. Je ne sais pas si c'est un problème ou non. –

+1

Non, open-open n'ouvre rien. Il * seulement * garantit que les variables liées sont (.close) d lorsque le flux de contrôle quitte le formulaire avec ouverture, que ce soit par exception ou retour normal. – dreish

+1

Oui, vous avez raison. Mon erreur. –

4

(Note: Tout cela devrait fonctionner tout va bien, mais je ne peux pas tester à ce moment S'il vous plaît donner votre chèque de santé mentale..)

Vous pouvez écrire

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

Cela semble assez alambiquée moi, cependant. Une autre approche:

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

Le motif ->/->> alambiquée de la première version pourrait être abstraite loin avec une macro:

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

Ensuite, vous pouvez écrire

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

Cela a bien propriété que vous pouvez utiliser plusieurs fois dans un seul formulaire doto tout en mélangeant dans les clauses doto régulière. Eh bien, c'est bien si ce genre de chose arrive plus souvent dans votre code, de toute façon. Sinon, la version basée sur let devrait fonctionner correctement.

(Si ce modèle arrive vraiment souvent pour vous, la macro pourrait être assouplie ... Il est tentant aussi de le rendre un peu moins flexible, mais plus joli, dire en remplaçant ~guard avec (when ~guard), donc Au point d'utilisation, on écrirait (doto-guard user (.setCredentials ...)). Cependant, toute raison profonde de choisir une version particulière devrait provenir d'un contexte plus large.)

La séparation en deux corps de fonctions est juste une question de style - je préfère ne pas écrire le nil nil lorsqu'aucune information d'identification n'est réellement fournie.

+0

Cela répond à la question littérale de Kurt, mais il pose la mauvaise question. Un code plus simple peut accomplir la même chose. – dreish

+0

Bien que je ressens quelque peu la "mauvaise question", Dreish a raison. +1 pour suggérer la surcharge sans utilisateur et mot de passe. –

+0

Désolé, je ne voulais pas offenser l'un d'entre vous. Je pose de mauvaises questions tout le temps. Je suis sûr que tout le monde le fait. – dreish

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

Le (with-open [client client]... semble un peu bizarre, mais bon, c'est un peu méchant code stateful.Si ce paramètre conditionnel dans doto arrive assez souvent, il peut justifier une macro, mais je sauterais à une fonction constructeur d'abord:

(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))) 
Questions connexes