Type the following in your terminal:
$ lein new clojurebridge global-growth
This is where we will be writing much of our code.
Clojure programs can be made up of multiple files, but we are going to use just this one for now.
Go to the command line and enter:
$ cd global-growth
$ lein run
Open src/global_growth/core.clj
.
What is in the -main
function?
(defn quotify
[quote author]
(str quote "\n\n-- " author))
(defn -main
[& args]
(println
(quotify (str "A man who carries a cat by the tail learns "
"something he can learn in no other way.")
"Mark Twain")))
Namespaces let you organize your code into logical sections.
;; in src/global_growth/core.clj
(ns global-growth.core)
Dependencies are code libraries others have written you can reuse in your project.
Open project.clj
and look for the
:dependencies
key.
:dependencies [[org.clojure/clojure "1.5.1"]
[clj-http "0.9.0"]
[cheshire "5.3.1"]]
;; in src/global_growth/core.clj
(ns global-growth.core
(:require [clj-http.client :as client]
[cheshire.core :as json]))
http://api.worldbank.org/countries/all/indicators/EN.POP.DNST?format=json&date=2010
[
{
"page": 1,
"pages": 6,
"per_page": "50",
"total": 252
},
[
{
"indicator": {
"id": "EN.POP.DNST",
"value": "Population density (people per sq. km of land area)"
},
"country": {
"id": "1A",
"value": "Arab World"
},
"value": "25.5287276250072",
"decimal": "0",
"date": "2010"
},
{
"indicator": {
"id": "EN.POP.DNST",
"value": "Population density (people per sq. km of land area)"
},
"country": {
"id": "S3",
"value": "Caribbean small states"
},
"value": "17.0236186241818",
"decimal": "0",
"date": "2010"
}
]
]
(client/get "http://api.worldbank.org/countries/all/indicators/EN.POP.DNST?format=json&date=2010")
;; elided and formatted
;;=> {:orig-content-encoding nil,
;; :request-time 109, :status 200,
;; :headers {"content-length" "10340",
;; "content-type" "application/json;charset=utf-8"},
;; :body "[{\"page\":1,\"pages\":6}]"}
(json/parse-string "[{\"page\":1,\"pages\":6}]" true)
;;=> ({:page 1, :pages 6})
Write a function called
get-population-density
that takes no
arguments, and returns Clojure data from the World Bank
API on population density.
You will need to make the web request, pull the
:body
value out of the response, and then
parse the JSON.
(get-population-density)
;;=> ({:page 1, :pages 6, :per_page "50", :total 252}
;; [{:indicator {:id "EN.POP.DNST", :value "Population density (people per sq. km of land area)"},
;; :country {:id "1A", :value "Arab World"}, :value "25.5287276250072", :decimal "0", :date "2010"},
;; ...])
(defn get-api
"Returns map representing API response."
[path params]
(let [url (str "http://api.worldbank.org" path)
query-params (merge params {:format "json" :per_page 10000})
response (json/parse-string
(:body
(client/get url {:query-params query-params})) true)
metadata (first response)
results (second response)]
{:metadata metadata
:results results}))
(get-api "/countries/all/indicators/EN.POP.DNST" {:date 2010})
;;=> {:metadata {:page 1, :pages 1, :per_page "10000", :total 252},
;; :results [{:indicator {:id "EN.POP.DNST",
;; :value "Population density (people per sq. km of land area)"},
;; :country {:id "1A", :value "Arab World"}, :value "25.5287276250072",
;; :decimal "0", :date "2010"} ...]}
Write a function get-country-and-value
that can take the return value of get-api
and get the country names and values out of that value.
get-country-and-value
should return a vector
of vectors.
(get-country-and-value
(get-api "/countries/all/indicators/EN.POP.DNST" {:date 2010}))
;;=> [["Arab World" "25.5287276250072"]
;; ["Caribbean small states" "17.0236186241818"]
;; ...]
Uncomment the definitions for
remove-aggregrate-countries
,
countries
, and
get-indicator-values
.
(defn get-indicator-values
"Returns indicator values for a specified year for all countries."
[indicator-code year]
(let [response (get-api (str "/countries/all/indicators/"
indicator-code)
{:date (str year)})
values (get-country-and-value response)]
(for [[country value] values
:when (and (not (nil? value))
(contains? @countries country))]
[country (read-string value)])))
(get-indicator-values "EN.POP.DNST" 2010)
What do you get?
-main
is the last function
in your file.In order to print out all the countries and population
densities, you will need a new statement,
doseq
.
doseq
works like for
but
executes its body and returns nothing.
(doseq [name ["Akeelah" "Bhamini" "Cierra"]]
(println name))
Using doseq
and println
,
write a -main
function that prints out all
the countries and their population densities from the
World Bank API.
Use (get-indicator-values "EN.POP.DNST"
2010)
to get the values you need.
Change your -main
function to only print
out the top 10 countries and their population densities.
You will need the sort-by
function to make
this work.