Instantly share code, notes, and snippets.

Embed
What would you like to do?
Using core.logic to query custom data sources.
(ns extend-core-logic.core
(:require [clojure.core.logic :refer :all]
[clojure.core.logic.protocols :refer [walk]]
[clojure.java.io :as jio]
[clojure.string :as string])
(:import [java.io BufferedReader StringReader]))
;; from: http://federalgovernmentzipcodes.us/
(defn load-db []
(let [data (java.io.BufferedReader. (java.io.StringReader. (slurp "/Users/tim/Downloads/free-zipcode-database.csv")))
data (->> (line-seq data)
(drop 1)
(map #(clojure.string/split % #","))
(map (fn [[idx zip _ nm]]
[(read-string zip)
(read-string nm)])))]
{:zip->city
(reduce
(fn [acc [k v]]
(assoc acc k v))
{}
data)
:city->zip
(reduce
(fn [acc [v k]]
(update-in acc [k] (fnil conj #{}) v))
{}
data)}))
(def ^:dynamic *db* (load-db))
(-> *db* :city->zip (get "DALLAS"))
(-> *db* :zip->city (get "75356"))
(defn debug [x]
(println x)
x)
(defn zipcodeo [zip city]
(fn [a]
(let [zip (walk a zip)
city (walk a city)]
(condp = [(not (lvar? zip))
(not (lvar? city))]
[true false] (unify a city (-> *db* :zip->city (get zip)))
[false true] (->> (-> *db* :city->zip (get city))
(map #(unify a zip %))
to-stream)
[true true] (when (= city (-> *db* :zip->city (get zip)))
a)))))
(run* [q]
(zipcodeo "75356" q))
(run* [q]
(zipcodeo q "DALLAS"))
(run* [q]
(fresh [x]
(membero x ["DALLAS" "DENVER"])
(== q "75356")
(zipcodeo q x)))
(run* [q]
(fresh [x]
(membero x ["DALLAS"])
(== q "75356")
(zipcodeo q x)))
(run* [q]
(fresh [x]
(membero x ["DENVER"])
(== q "75356")
(zipcodeo q x)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment