(defn parse-args
([args]
(parse-args args {}))
([[fst sec & more] rst]
(let [value? (fn [x] (and (not (keyword? x))
(not (map? x))))]
(cond
(and (keyword? fst)
(keyword? sec)) (parse-args (cons sec more) (merge rst {fst true}))
(and (keyword? fst)
(value? sec)) (parse-args more (merge rst {fst sec}))
:else rst
))))
*im new to clojure
for example there is a vec like below:
[:enchant :type "Fire Aspect" :level 123]
try to convert it to:
{:enchant true :type "Fire Aspect" :level 123}
note that the original vec has been somehow 'interleaved'
but not every key has its 'value' (like :enchant
)
and i just want to find out those and treat them as a boolean value
with true
as their default value
i've tried to use:
(defn parse-arg [args toggle-coll]
(let [is-value? #(not (and (keyword? %)
(map? %1)))]
(reduce (fn [k1 k2]
(merge
(cond
(and (keyword? k1)
(keyword? k2)) ({} {k1 true})
(and (keyword? k1)
(is-value? k2)) ({} {}) ; and soon i found this method is difficult and clumsy
(and (map? k1)
(is-value? k2)) ({} {})
(and (map? k1)
(keyword? k2)) ({} {})
;; omitted)
)
)
args)))
we can also process the input data by the windows of 2 items and insert true
between two keywords:
(defn parse-args [data]
(->> (concat data [::end])
(partition 2 1)
(mapcat (fn [[a :as pair]]
(if (every? keyword? pair)
[a true]
[a])))
(apply hash-map)))
the ::end
kv is added to handle the dangling keyword in the end of the sequence, if any.
user> (parse-args [:a :b 1 :c 10 :d])
;;=> {:c 10, :b 1, :d true, :a true}