Skip to content

Instantly share code, notes, and snippets.

@nikolavojicic
Last active March 23, 2022 23:31
Show Gist options
  • Save nikolavojicic/a89d05e539214e7433eeb7ca4b70a3b7 to your computer and use it in GitHub Desktop.
Save nikolavojicic/a89d05e539214e7433eeb7ca4b70a3b7 to your computer and use it in GitHub Desktop.
Various pure functions
(with-test
(defn ->and
[id-col id-val rec]
(if id-val
(reduce-kv
(fn [ret col val]
(if val
(-> ret
(update 0 #(str % " AND " (name col) " = ?"))
(conj val))
(update ret 0 #(str % " AND " (name col) " IS NULL"))))
[(str (name id-col) " = ?") id-val] rec)
(throw (IllegalArgumentException. "Nil id-val"))))
(is (= (->and :id 1 {:to nil})
["id = ? AND to IS NULL" 1]))
(is (= (->and :id 1 {:to "1978-08-07"})
["id = ? AND to = ?" 1 "1978-08-07"]))
(is (= (->and :id 1 {:from nil :to "1978-08-07"})
["id = ? AND from IS NULL AND to = ?" 1 "1978-08-07"]))
(is (= (->and :id 1 {}) (->and :id 1 nil) ["id = ?" 1]))
(is (thrown? IllegalArgumentException (->and :id nil {}))))
(with-test
(defn ->in
([coll]
(if (seq coll)
(str/join "," (-> coll count (repeat "?")))
(throw (IllegalArgumentException. "Empty coll"))))
([sql coll] (apply vector (format sql (->in coll)) coll)))
(is (= (->in (range 5))
"?,?,?,?,?"))
(is (= (->in "col IN (%s)" (range 3))
["col IN (?,?,?)" 0 1 2]))
(is (= (->in "col IN (%s)" [1])
["col IN (?)" 1]))
(stest/with-instrument-disabled
(are [x] (thrown? IllegalArgumentException x)
(db/->in [])
(db/->in nil)
(db/->in "col IN (%s)" [])
(db/->in "col IN (%s)" nil))))
(s/fdef ->in
:args (s/or :arg1 (s/cat :coll (s/coll-of any? :min-count 1 :distinct true))
:arg2 (s/cat :sql (s/and string? #(str/includes? % "IN (%s)"))
:coll (s/coll-of any? :min-count 1 :distinct true))))
(defn batch-delimiters
[batch-size end]
(->> end
(iterate #(- % batch-size))
(take-while pos?)
(reverse)
(#(conj % 0))
(partition 2 1)))
(with-test
(defn diff
[old new]
(let [kws (set (concat (keys old) (keys new)))
ret (reduce
(fn [ret kw]
(let [old (kw old), new (kw new)]
(if (not= old new)
(-> ret
(update 0 #(assoc % kw old))
(update 1 #(assoc % kw new)))
ret)))
[{} {}] kws)]
(mapv not-empty ret)))
(is (= (diff {:foo "bar"} {})
[{:foo "bar"} {:foo nil}]))
(is (= (diff {} {:foo "bar"})
[{:foo nil} {:foo "bar"}]))
(is (= (diff {:foo "bar1"} {:foo "bar2"})
[{:foo "bar1"} {:foo "bar2"}]))
(is (= (diff {:foo "bar" :bar "foo1"}
{:foo "bar" :bar "foo2"})
[{:bar "foo1"} {:bar "foo2"}]))
(is (= (diff {:foo "bar1" :bar "foo1"}
{:foo "bar2" :bar "foo2"})
[{:bar "foo1" :foo "bar1"}
{:bar "foo2" :foo "bar2"}]))
(is (= (diff {} {})
(diff {:foo "bar"}
{:foo "bar"})
(diff {:foo "bar" :bar "foo"}
{:foo "bar" :bar "foo"})
[nil nil]))
(is (= (diff nil nil) [nil nil]))
(is (thrown? ClassCastException (diff [1] [1]))))
(with-test
(defn fib
([] (fib 0 1))
([x y] (lazy-seq (cons x (fib y (+' x y))))))
(is (= (take 2 (fib)) [0 1]))
(is (= (take 3 (fib)) [0 1 1]))
(is (= (take 4 (fib)) [0 1 1 2]))
(is (= (take 5 (fib)) [0 1 1 2 3]))
(is (= (last (take 101 (fib))) 354224848179261915075N)))
(with-test
(defn pretty-duration
[nanos]
(assert (>= nanos 0))
(let [unit java.util.concurrent.TimeUnit/NANOSECONDS
msec (.toMillis unit nanos)
sec (.toSeconds unit nanos)
min (.toMinutes unit nanos)
hour (.toHours unit nanos)
day (.toDays unit nanos)]
(format "%s%02d:%02d:%02d.%03d"
(cond (= day 0) ""
(= day 1) "1 day, "
(> day 1) (str day " days, "))
(- hour (* day 24))
(- min (* hour 60))
(- sec (* min 60))
(- msec (* sec 1000)))))
(is (thrown? NullPointerException (pretty-duration nil)))
(is (thrown? AssertionError (pretty-duration -1)))
(is (= (pretty-duration 0) "00:00:00.000"))
(is (= (pretty-duration 1e5) "00:00:00.000"))
(is (= (pretty-duration 1e6) "00:00:00.001"))
(is (= (pretty-duration Integer/MAX_VALUE) "00:00:02.147"))
(is (= (pretty-duration (* 8.64 1e13)) "1 day, 00:00:00.000"))
(is (= (pretty-duration Long/MAX_VALUE) "106751 days, 23:47:16.854"))
(is (thrown-with-msg?
IllegalArgumentException
#"Value out of range for long: 9223372036854775808"
(pretty-duration (inc' Long/MAX_VALUE)))))
(with-test
(defn remove-nil-vals
[m]
(into {} (remove (comp nil? val) m)))
(is (= (remove-nil-vals {}) {}))
(is (= (remove-nil-vals nil) {}))
(is (= (remove-nil-vals {:bar 1
:baz false})
{:bar 1 :baz false}))
(is (= (remove-nil-vals {:foo nil
:bar 1
:baz false})
{:bar 1 :baz false}))
(is (= (remove-nil-vals {:foo nil
:bar 1
:baz false
:qux nil})
{:bar 1 :baz false})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment