3

I'm working on a Clojure application that will interact with a web API to return a random result meeting a specific criterion. Because of the limitations of the API, I have to retrieve a number of results and use Clojure to filter out an appropriate one.

I would say 99% or more of the time, at least one of the results from the first request will meet my criterion. But because of that other 1%, I feel I have to build in functionality to make multiple requests. Obviously the odds are pretty good that the second request will be successful but I'm leery about writing a function that recurs endlessly until it gets the right result in case something goes wrong and I end up DDoSing the API.

My first thought was to build a counter into the function and limit it to, say, five requests. But that feels a bit procedural as an approach. What's the idiomatic Clojure way to go about this?

Here's what I have so far:

(ns randchar.api
  (:require [clj-http.client :as client]))

(defn api-request 
  [url]
  (get-in
    (client/request
      {:url url
       :method :get
       :content-type :json
       :as :json}) [:body :results]))

(defn filter-results
  "Returns the first result that meets the criterion."
  [results criterion]
  (take 1 
        (filter #(= (get-in % [:nested :sub-nested]) criterion) results)))

(defn build-url
  "Returns a url with randomized query string for the api request; not shown."
  []
  )

(defn return-result
  "Currently recurs endlessly if no results meet the criterion."
  [criterion]
  (let [x (filter-results (api-request (build-url)) criterion)]
    (if (not (empty? x))
      x
      (recur))))

1 Answer 1

3

You can try something like:

(defn return-result
  [criterion count]
  (->> (repeatedly count #(filter-results (api-request build-url) criterion))
       (filter (complement empty?))
       first))
Sign up to request clarification or add additional context in comments.

2 Comments

That's exactly what I was looking for, thank you. Much cleaner than what I had in mind.
Updated to use repeatedly to make it more clean

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.