Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 1046339
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T16:07:54+00:00 2026-05-16T16:07:54+00:00

I’m looking for a more idiomatic way, if possible, to write the following clojure

  • 0

I’m looking for a more idiomatic way, if possible, to write the following clojure code:

(import '(System.Net HttpWebRequest NetworkCredential)
        '(System.IO StreamReader)) 

(defn downloadWebPage
  "Downloads the webpage at the given url and returns its contents."
  [^String url ^String user ^String password]
  (def req (HttpWebRequest/Create url))
  (.set_Credentials req (NetworkCredential. user password ""))
  (.set_UserAgent req ".NET")
  (def res (.GetResponse req))
  (def responsestr (.GetResponseStream res))
  (def rdr (StreamReader. responsestr))
  (def content (.ReadToEnd rdr))
  (.Close rdr)
  (.Close responsestr)
  (.Close res)
  content
  )

This is on ClojureCLR and works. (the fact that it’s the CLR variant doesn’t matter much)

I’d like to get rid of the defs (replace by lets? can they refer to each other?)

How about a better way to get to the stream – keeping in mind that .. chaining won’t work because I need to Close the streams later on.

EDIT: After the answer, I found a much easier way in .NET to download a web page using the WebClient class. I still used many of Michal’s recommended approaches – just wanted to record what I now believe to be the best answer:

(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.)
                        (.set_Credentials (NetworkCredential. user password "")))]
      (.DownloadString client url)))
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T16:07:54+00:00Added an answer on May 16, 2026 at 4:07 pm

    The code from the question can be rewritten fairly idiomatically like so (modulo any typos — here’s hoping there are none):

    (defn download-web-page
      "Downloads the webpage at the given url and returns its contents."
      [^String url ^String user ^String password]
      (let [req (doto (HttpWebRequest/Create url)
                  (.set_Credentials (NetworkCredential. user password ""))
                  (.set_UserAgent ".NET"))
            response        (.GetResponse req)
            response-stream (.GetResponseStream res)
            rdr             (StreamReader. response-stream)
            content (.ReadToEnd rdr)]
        (.Close rdr)
        (.Close response-stream)
        (.Close response)
        content))
    

    Assuming the .NET version of with-open calls .Close at the bound objects (as I expect it might, but won’t be able to check — no .NET REPL at hand) and that .readToEnd eagerly consumes the whole stream, this could be further simplified to

    Update: Just checked that ClojureCLR’s with-open calls .Dispose on the bound objects. If that is ok in place of .Close, great; if .Close is required, you can write your own version of with-open to use .Close instead (possibly copying most of the original):

    (defn download-web-page
      "Downloads the webpage at the given url and returns its contents."
      [^String url ^String user ^String password]
      (let [req (doto (HttpWebRequest/Create url)
                  (.set_Credentials (NetworkCredential. user password ""))
                  (.set_UserAgent ".NET"))]
        (with-open [response        (.GetResponse req)
                    response-stream (.GetResponseStream res)
                    rdr             (StreamReader. response-stream)]
          (.ReadToEnd rdr))))
    

    Some comments:

    1. Don’t use def, defn etc. anywhere except at top level unless you really know you need to do that. (Actually using them immediately inside a top-level let is occasionally useful if you need the object being created to close over the let-bound locals… Anything more funky than that should receive very careful scrutiny!)

      def & Co. create top level Vars or reset their root bindings; doing so in the course of a programme’s regular operation is completely contrary to the functional spirit of Clojure. Perhaps more importantly from a practical POV, any function which relies on "owning" a bunch of Vars can only be executed by one thread at a time; there’s no reason why download-web-page should be thus limited.

    2. let-introduced bindings may not be mutually recursive; later bindings may refer to earlier bindings, but not the other way around. Mutually recursive local functions may be introduced with letfn; other types of mutually recursive objects may be somewhat less convenient to create outside of top level (though by no means impossible). The code from the question doesn’t rely on mutually recursive values, so let works fine.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.