I'm learning Clojure and I'm doing a little thing that reads direct messages from Twitter using twitter-api wrapper. The code doing that is below.

(ns twitterbot.my-twitter
[clojure.edn :as edn]
[clojure.string :as string]))

(def ^:private oauth-credentials
(make-oauth-creds (credentials-from-file :consumerkey)
(credentials-from-file :consumersecret)
(credentials-from-file :usertoken)
(credentials-from-file :usersecret)))

(defn- has-url? [message]
(seq (:urls (:entities message))))

(defn- trusted-user? [message]
(= (credentials-from-file :trusteduser) (:sender_screen_name message)))

(defn- get-url [message]
(:expanded_url (nth (:urls (:entities message)) 0)))

(let [messages (direct-messages :oauth-creds oauth-credentials)]
(map get-url (filter has-url? (filter trusted-user? (:body messages))))))


As I'm new to Clojure, I would like to know whether I'm doing things in the correct way and how to do them better. I feel like the coding style and layout is off at least in links-from-direct-messages, but I even though I tried to follow this style guide, I'm not sure how it should be. Also as the data structure from Twitter is quite nested, I wonder how I should be going through them.

Your get-url function could just use get-in:

(defn- get-url [message]
(get-in message [:entities :urls 0 :expanded_url]))


links-from-direct-messages has quite a lot of nested calls. When you've got a bunch of nested operations like that it can be nice to re-write them using one of the threading macros (-> and ->>). These take an input, and then "thread" it through a series of forms as the first (in the case of ->) or last (in the case of ->>) argument. By doing this, they allow you to rewrite nested calls sequentially.

This is mentioned in the style guide you linked.

In the case of links-from-direct-messages you're calling map and filter, which both accept the collection as their last argument, so you can use ->>:

(defn links-from-direct-messages []
(->> (direct-messages :oauth-creds oauth-credentials)
:body
(filter trusted-user?)
(filter has-url?)
(map get-url)))