I have not found a standard Elisp library function to merge two property lists, like this:
(setq pl nil)
(setq pl (plist-put pl 'key-1 'value-1))
(setq pl (plist-put pl 'key-2 'value-2))
I could build something with dolist
, but before I do, I would like to check that I'm not overlooking an existing function in some library.
Updates, based on the comments:
- In response to the "many-ways" comment:
I would imagine that there isn't such a function because there are different (and possibly valid) answers possible to the question: what to do when you have duplicate property names with distinct values?
Yes, there is a question on how to merge duplicates, but there are relatively few ways to address that. I see two general approaches. First, argument order could resolve the duplicates; e.g. rightmost wins, as in Clojure's merge. Second, the merge could delegate to a user-provided callback function, as in Ruby's merge.
In any case, the fact that there are different ways of doing it does not prevent many other language standard libraries from providing a merge function. The same general argument could be said of sorting, and yet Elisp provides sorting functionality.
- "Could you elaborate?" / "Please specify the behavior you are looking for precisely."
Generally speaking, I'm open to what the Elisp community uses. If you would like a specific example, here would be one example that would work:
(a-merge-function '(k1 1) '(k2 2 k3 3) '(k3 0))
And returns
'(k1 1 k2 2 k3 0))
This would be a rightmost-wins style, like Clojure's merge.
- "They're lists, so just append?"
No, append
does not preserve property list semantics. This:
(append '(k1 1 k2 2) '(k2 0))
Returns this:
(k1 1 k2 2 k2 0)
append is a built-in function in `C source code'.
(append &rest SEQUENCES)
Concatenate all the arguments and make the result a list. The result is a list whose elements are the elements of all the arguments. Each argument may be a list, vector or string. The last argument is not copied, just used as the tail of the new list.
- "And your example does not show anything like a merge - it does not even show two property lists."
Yes it does; it does the merge step by step. It shows how doing a merge using the Elisp's documented property list functions is painfully verbose:
(setq pl nil)
(setq pl (plist-put pl 'key-1 'value-1))
(setq pl (plist-put pl 'key-2 'value-2))
Just display the resulting output value from pl
:
(key-1 value-1 key-2 value-2)
To reiterate, I am capable of writing a function to solve this problem, but I first wanted to figure out if such a function exists somewhere in common use.
Finally, if you downvoted the question because you found it unclear, I would ask that you reconsider now that I've gone to some effort to clarify. This is not a lack of research. The Elisp documentation on "Lists" does not answer the question.
append
? – abo-abo Dec 16 '14 at 9:18append
:(let ((args '((:a 1 :b 1) (:b 2) (:a 3)))) (apply #'append (reverse args))) => (:a 3 :b 2 :a 1 :b 1)
which is the same as(:a 3 :b 2 :a 1)
as long as you only use plist functions to access the plist. – tarsius Dec 16 '14 at 20:04plist-get
norplist-member
seem to care if there are multiple identical keys. It looks like they behave analogously to alists in this respect:(plist-get '(:a "a" :b "b" :a "c") :a) ==> "a"
. Meanwhile,(plist-put '(:a "a" :b "b" :a "c") :a "d")
replaces the value of the first:a
key but not the second. – Dan♦ Dec 16 '14 at 20:55