Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
closed by

This functions which I think they are usually used could be shortened

(let [coll (get-coll)]
  (if (seq coll) 
    (handle-true coll)
    (handle-false)))

(when-let [x (seq ...)])

(if-let [x (seq ...)])

Like:

(if-seq-let [coll (get-coll)]
  (handle-true coll)
  (handle-false))

(when-seq-let [c (get-coll)]
  (handle-true1 coll)
  (handle-true2 coll))

Proposal based on if-let and when-let.

(defmacro ^{:private true} assert-args
  [& pairs]
  `(do (when-not ~(first pairs)
         (throw (IllegalArgumentException.
                  (str (first ~'&form) " requires " ~(second pairs) " in " ~'*ns* ":" (:line (meta ~'&form))))))
       ~(let [more (nnext pairs)]
          (when more
            (list* `assert-args more)))))

(defmacro if-seq-let
  "bindings => binding-form test

  If test is seq, evaluates then with binding-form bound to the value of
  test, if not, yields else"
  ([bindings then]
   `(if-let ~bindings ~then nil))
  ([bindings then else & oldform]
   (assert-args
     (vector? bindings) "a vector for its binding"
     (nil? oldform) "1 or 2 forms after binding vector"
     (= 2 (count bindings)) "exactly 2 forms in binding vector")
   (let [form (bindings 0) tst (bindings 1)]
     `(let [temp# ~tst]
        (if (seq temp#)
          (let [~form temp#]
            ~then)
          ~else)))))

(defmacro when-seq-let
  "bindings => binding-form test

  When test is seq, evaluates body with binding-form bound to the value of test"
  [bindings & body]
  (assert-args
    (vector? bindings) "a vector for its binding"
    (= 2 (count bindings)) "exactly 2 forms in binding vector")
  (let [form (bindings 0) tst (bindings 1)]
    `(let [temp# ~tst]
       (when (seq temp#)
         (let [~form temp#]
           ~@body)))))
...