antlockyer
antlockyer

Reputation: 23

Errors when trying to pass args in clojure using clj-http

hopefully this is something simple for the more experienced out there. I am using clj-http and trying to pass the command line arg int it (to take a URL). I am an absolute Clojure beginer but I have managed to pass the args through to a ptintln which works.

(ns foo.core
  (:require [clj-http.client :as client]))

(defn -main
  [& args]
  (def url (str args))
  (println url)
  (def resp (client/get url))
  (def headers (:headers resp))
  (def server (headers "server"))
  (println server))

Error message

Ants-MacBook-Pro:target ant$ lein run "http://www.bbc.com"
("http://www.bbc.com")
Exception in thread "main" java.net.MalformedURLException: no protocol: ("http://www.bbc.com")

This works

(def resp (client/get "http://www.bbc.com"))

thanks in advance.

Upvotes: 2

Views: 261

Answers (1)

Max Noel
Max Noel

Reputation: 8910

args is a list, which means that calling str on it returns the representation of the list, complete with parentheses and inner quotes, as you can see in your error trace:

(println (str '("http://www.bbc.com")))
;; prints ("http://www.bbc.com")

Of course, URLs don't start with parentheses and quotes, which is why the JVM tells you your URL is malformed.

What you really want to pass to get is not the string representation of your argument list, but your first argument:

(let [url (first args)] 
  (client/get url)) ;; Should work!

In addition, you should never use def calls within functions -- they create or rebind vars at the toplevel of your namespace, which don't want.

What you should be using instead is let forms, which create local variables (like url in my example). For more information on let, look at http://clojure.org/special_forms.

I'd probably structure your code like so:

(defn -main
  [& args]
  (let [url (first args)
        resp (client/get url)
        server (get-in resp [:headers "server"])]
    (println url)
    (println server)))

Upvotes: 2

Related Questions