Reputation: 938
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))))
Upvotes: 3
Views: 367
Reputation: 33657
You can try something like:
(defn return-result
[criterion count]
(->> (repeatedly count #(filter-results (api-request build-url) criterion))
(filter (complement empty?))
first))
Upvotes: 3