   "Validate a parsed argument."
   [arg {:keys [optional vararg valid-fn] :as arg-descriptor}]
   (cond
+   (map? arg) arg              ; propagate any error from the parse-fn
+
    (and (= arg ::missing) (not (or optional vararg)))
    {:invalid-args (assoc arg-descriptor :value arg :reason :missing)}
 

  [(merge-with conj res
               (validate-arg
                (if (seq args)
                  (parse-arg (first args) arg-descriptor-map)
                  ::missing)
                arg-descriptor-map))
   (rest args)])

(defn invalid-args-message
  [invalid-args]
  (reduce
   (fn [s {:keys [arg-name value reason error value]}]
     (str s "Invalid argument for '" arg-name "'"
          (when value (str " with value '" value "'"))
          ". "
          (condp = reason
            :missing "Argument missing"
            :invalid "Argument invalid"
            :not-parseable "Argument wrong format")
          "."
          (when error (str " " error))))
   ""
   invalid-args))

