I've this function and I don't know how to implement it. I only know how to use concat, but it's wrong because it only adds and I also need to update.
Can anyone help me?
This is the function:
(defn update-env
[env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(concat env-global (list key value))))
This is the code I need to run: (update-env '(+ add - sub x 1 y 2) 'x 3)
This is the result it should give: (+ add - sub x 3 y 2)
Thanks in advance!
the trick is to operate on collection's elements pairwise something alike the common lisp's plist
. You can make up something like this:
(defn plist-assoc [key new-val plist]
(->> plist
(partition 2)
(mapcat (fn [[k v]] [k (if (= k key) new-val v)]))))
user> (plist-assoc 'x 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 3 y 2)
user> (plist-assoc 'z 3 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2)
so than your function looks like this:
(defn update-env [env-global key value]
(if (and (list? value) (= (first value) '*error*))
env-global
(plist-assoc key value env-global)))
user> (update-env '(+ add - sub x 1 y 2) 'x 3)
;;=> (+ add - sub x 3 y 2)
update if you need to update or insert new value, you can use something like this instead:
(defn assoc-plist2 [key new-val plist]
(let [[l r] (->> plist
(partition 2)
(split-with (comp nil? #{key} first)))]
(apply concat `(~@l ~[key new-val] ~@(rest r)))))
user> (assoc-plist2 'x 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 10 y 2)
user> (assoc-plist2 'z 10 '(+ add - sub x 1 y 2))
;;=> (+ add - sub x 1 y 2 z 10)