Easy way to merge plists? - lisp

Is there an easy way in Common Lisp to merge two plists? Or from another point of view: is there a way to remove duplicates from a plist? I know I can just append plists (and GETF will take the first one it finds), but I'd like to not keep accumulating unused keys as my app runs.
I'm thinking about something like (loop for p on my-plist by #'cddr ...), but there's often an easier way than my first thought!

You could start from this primitive version:
(defun merge-plist (p1 p2)
(loop with notfound = '#:notfound
for (indicator value) on p1 by #'cddr
when (eq (getf p2 indicator notfound) notfound)
do (progn
(push value p2)
(push indicator p2)))
p2)
CL-USER 104 > (merge-plist '(a 1 b 2 c 3) '(a 2 b 4))
(C 3 A 2 B 4)

Related

Order Lists by CAR

I need to be able to compare two cars of a list to sort them im LISP.
Lists '(e d) (a b)
I want to compare the cars (e and a). This works using eql. If they don't match, I want to order the lists alphabetically, so (a b) (e d).
I'm missing the part where I can see which character is 'bigger', so the check if e or a should come first. I've tried converting them to ascii codes, but that doesn't work for (car a). Using arithmetic operators such as '<' and '>' also doesn't work. Does anyone have an idea on how to do this?
Use string> without symbol-name:
CL-USER 6 > (string> 'a 'b)
NIL
CL-USER 7 > (string< 'a 'b)
0
For the sake of completeness, here is how you should use it inside sort to achieve desired result (sort is destructive- modifies used sequence, so I also used copy-tree to avoid that effect):
(let ((data '((e d) (a b))))
(sort (copy-tree data)
(lambda (x y) (string< (car x) (car y)))))
((A B) (E D))
A symbol is distinct from a string.
CL-USER> (symbol-name 'foo)
"FOO"
A string (a sequence of characters) can be compared in the manner you seem to be interested in.
CL-USER> (string> "FOO" "BOO")
0
CL-USER> (string< "FOO" "BOO")
NIL

Idiomatic way in Emacs Lisp to visit each cons cell in a list?

i would like to visit all the cons cells in a list and perform some action on them (including such things as setcar). is there an idiomatic way of doing this?
i can, i think, do something like this
(progn
(setq a (list 1 2 3 4 5 6))
(setq okay a)
(while okay
(if (eq (car okay) 3)
(setcar okay 22))
(setq okay (cdr okay))))
(where the if expression is my "application logic", say.)
but, if there's a terser way of doing this, i'd be interested in hearing about it.
If you want to mutate the cars of the list, then in recent emacsen the likely think you want is cl-mapl, which maps a function over successive tails of the list. This is essentially Common Lisp's mapl function: CL has
maplist which maps a function over tails and returns a new list of the values of the function, so (maplist (lambda (e) e) '(1 2 3)) is ((1 2 3) (2 3) (3));
mapl which is like maplist but returns the original list.
elisp (courtesy of some now-standard library) now has both cl-mapl and cl-maplist.
So:
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail 0))
y)
y)
(0 0 0 0 0 0 0)
or
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail (if (cdr tail) (cadr tail) 'fish)))
y)
y)
(2 3 4 5 6 7 fish)
(In neither of these cases do you need to make sure that y is returned: I just did it to make it clear that y is being destructively modified by this.)
(setq a (mapcar (lambda (x) (if (equal x 3) 22 x)) a))
That sets the value of variable a to the result of changing any members of a that are 3 to 22.
Choose the equality operator you want, equal, eql, or =, depending on whether you know that either all list members are numbers (use =) or you know that they are either numbers or you want to test object equality otherwise, (use eql), or you don't know what they might be (use equal).
You haven't indicated any need to do list-structure modification (setcar). It appears that all you care about is for a to be a list as I described.

Writing the Foo Function In LISP With the following Specification

I am struggling to find the right approach to solve the following function
(FOO #'– '(1 2 3 4 5))
=> ((–1 2 3 4 5) (1 –2 3 4 5) (1 2 –3 4 5) (1 2 3 –4 5) (1 2 3 4 –5))
The first Parameter to the foo function is supposed to be a function "-" that has to be applied to each element returning a list of list as shown above. I am not sure as to what approach I can take to create this function. I thought of recursion but not sure how I will preserve the list in each call and what kind of base criteria would I have. Any help would be appreciated. I cannot use loops as this is functional programming.
It's a pity you cannot use loop because this could be elegantly solved like so:
(defun foo (fctn lst)
(loop
for n from 0 below (length lst) ; outer
collect (loop
for elt in lst ; inner
for i from 0
collect (if (= i n) (funcall fctn elt) elt))))
So we've got an outer loop that increments n from 0 to (length lst) excluded, and an inner loop that will copy verbatim the list except for element n where fctn is applied:
CL-USER> (foo #'- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
Replacing loop by recursion means creating local functions by using labels that replace the inner and the outer loop, for example:
(defun foo (fctn lst)
(let ((len (length lst)))
(labels
((inner (lst n &optional (i 0))
(unless (= i len)
(cons (if (= i n) (funcall fctn (car lst)) (car lst))
(inner (cdr lst) n (1+ i)))))
(outer (&optional (i 0))
(unless (= i len)
(cons (inner lst i) (outer (1+ i))))))
(outer))))
Part of the implementation strategy that you choose here will depend on whether you want to support structure sharing or not. Some of the answers have provided solutions where you get completely new lists, which may be what you want. If you want to actually share some of the common structure, you can do that too, with a solution like this. (Note: I'm using first/rest/list* in preference to car/car/cons, since we're working with lists, not arbitrary trees.)
(defun foo (operation list)
(labels ((foo% (left right result)
(if (endp right)
(nreverse result)
(let* ((x (first right))
(ox (funcall operation x)))
(foo% (list* x left)
(rest right)
(list* (revappend left
(list* ox (rest right)))
result))))))
(foo% '() list '())))
The idea is to walk down list once, keeping track of the left side (in reverse) and the right side as we've gone through them, so we get as left and right:
() (1 2 3 4)
(1) (2 3 4)
(2 1) (3 4)
(3 2 1) (4)
(4 3 2 1) ()
At each step but the last, we take the the first element from the right side, apply the operation, and create a new list use revappend with the left, the result of the operation, and the rest of right. The results from all those operations are accumulated in result (in reverse order). At the end, we simply return result, reversed. We can check that this has the right result, along with observing the structure sharing:
CL-USER> (foo '- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
By setting *print-circle* to true, we can see the structure sharing:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '(1 2 3 4 5)))
(list l (foo '- l)))
((1 . #1=(2 . #2=(3 . #3=(4 . #4=(5))))) ; input L
((-1 . #1#)
(1 -2 . #2#)
(1 2 -3 . #3#)
(1 2 3 -4 . #4#)
(1 2 3 4 -5)))
Each list in the output shares as much structure with the original input list as possible.
I find it easier, conceptually, to write some of these kind of functions recursively, using labels, but Common Lisp doesn't guarantee tail call optimization, so it's worth writing this iteratively, too. Here's one way that could be done:
(defun phoo (operation list)
(do ((left '())
(right list)
(result '()))
((endp right)
(nreverse result))
(let* ((x (pop right))
(ox (funcall operation x)))
(push (revappend left (list* ox right)) result)
(push x left))))
The base case of a recursion can be determined by asking yourself "When do I want to stop?".
As an example, when I want to compute the sum of an integer and all positive integers below it, I can do this recusively with a base case determined by answering "When do I want to stop?" with "When the value I might add in is zero.":
(defun sumdown (val)
(if (zerop val)
0
(+ (sumdown (1- val)) val)))
With regard to 'preserve the list in each call', rather than trying to preserve anything I would just build up a result as you go along. Using the 'sumdown' example, this can be done in various ways that are all fundamentally the same approach.
The approach is to have an auxiliary function with a result argument that lets you build up a result as you recurse, and a function that is intended for the user to call, which calls the auxiliary function:
(defun sumdown1-aux (val result)
(if (zerop val)
result
(sumdown1-aux (1- val) (+ val result))))
(defun sumdown1 (val)
(sumdown1-aux val 0))
You can combine the auxiliary function and the function intended to be called by the user by using optional arguments:
(defun sumdown2 (val &optional (result 0))
(if (zerop val)
result
(sumdown2 (1- val) (+ val result))))
You can hide the fact that an auxiliary function is being used by locally binding it within the function the user would call:
(defun sumdown3 (val)
(labels ((sumdown3-aux (val result)
(if (zerop val)
result
(sumdown3-aux (1- val) (+ val result)))))
(sumdown3-aux val 0)))
A recursive solution to your problem can be implemented by answering the question "When do I want to stop when I want to operate on every element of a list?" to determine the base case, and building up a result list-of-lists (instead of adding as in the example) as you recurse. Breaking the problem into smaller pieces will help - "Make a copy of the original list with the nth element replaced by the result of calling the function on that element" can be considered a subproblem, so you might want to write a function that does that first, then use that function to write a function that solves the whole problem. It will be easier if you are allowed to use functions like mapcar and substitute or substitute-if, but if you are not, then you can write equivalents yourself out of what you are allowed to use.

Adding to the end of list in LISP [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
what is the ‘cons’ to add an item to the end of the list?
After watching many tutorials on lisp and searching high and low on google for answers, I still cannot figure out how to add to the end of a list in LISP.
I want my function to add 'a at the end of the list '(b c d) but I only know how to add it in front. Can someone help me use cons correctly to add 'a at the end of the list? Here is my code. Thanks in advance.
(defun AddRt (a list)
(cond
((null list)
0)
(t
(princ (cons a (cons (car list) (cdr list))))
)))
(AddRt 'a '(b c d))
Either push to last, or use nconc:
> (defparameter a (list 1 2 3))
A
> (push 4 (cdr (last a)))
(4)
> a
(1 2 3 4)
> (nconc a (list 5))
(1 2 3 4 5)
> a
(1 2 3 4 5)
note that these are destructive operators, i.e., they modify the object which is the value of a, not just the binding of a.
This is why, BTW, you should never use nconc on quoted lists, like (nconc '(1 2 3) '(4 5 6)).
PS. Note that adding to the end of a list requires its full
traversal and is thus an O(length(list)) operation. This may be a bad
idea if your lists are long, so people often use the
push/nreverse
idiom, e.g.,
(let (range)
(dotimes (i 10 (nreverse range))
(push i range)))
==> (0 1 2 3 4 5 6 7 8 9)
You may use a recursive function. Also, you should avoid using princ inside.
The following function, endcons, does exactly the same thing as cons, except the value is added at the end.
(defun endcons (a v)
(if (null v) (cons a nil) (cons (car v) (endcons a (cdr v)))))
(endcons 'a '(b c d))
Of course, you could also use append:
(append '(b c d) '(a))
See also this related question: what is the 'cons' to add an item to the end of the list?
One way is to reverse the list. Add the element to beginning of the reversed list. And then finally reverse the whole list.
Scheme code:
(define (add-to-tail l x)
(reverse (cons x (reverse l)))
But if this is an operation you need often, then I'd suggest you find a data structure other than (single linked) lists.

LISP - count occurences of every value in a list

I apologize for the bad English..
I have a task to write a function called "make-bag" that counts occurences of every value in a list
and returns a list of dotted pairs like this: '((value1 . num-occurences1) (value2 . num-occurences2) ...)
For example:
(make-bag '(d c a b b c a))
((d . 1) (c . 2) (a . 2) (b . 2))
(the list doesn't have to be sorted)
Our lecturer allows us to us functions MAPCAR and also FILTER (suppose it is implemented),
but we are not allowed to use REMOVE-DUPLICATES and COUNT-IF.
He also demands that we will use recursion.
Is there a way to count every value only once without removing duplicates?
And if there is a way, can it be done by recursion?
First of, I agree with Mr. Joswig - Stackoverflow isn't a place to ask for answers to homework. But, I will answer your question in a way that you may not be able to use it directly without some extra digging and being able to understand how hash-tables and lexical closures work. Which in it's turn will be a good exercise for your advancement.
Is there a way to count every value only once without removing duplicates? And if there is a way, can it be done by recursion?
Yes, it's straight forward with hash-tables, here are two examples:
;; no state stored
(defun make-bag (lst)
(let ((hs (make-hash-table)))
(labels ((%make-bag (lst)
(if lst
(multiple-value-bind (val exists)
(gethash (car lst) hs)
(if exists
(setf (gethash (car lst) hs) (1+ val))
(setf (gethash (car lst) hs) 1))
(%make-bag (cdr lst)))
hs)))
(%make-bag lst))))
Now, if you try evaluate this form twice, you will get the same answer each time:
(gethash 'a (make-bag '(a a a a b b b c c b a 1 2 2 1 3 3 4 5 55)))
> 5
> T
(gethash 'a (make-bag '(a a a a b b b c c b a 1 2 2 1 3 3 4 5 55)))
> 5
> T
And this is a second example:
;; state is stored....
(let ((hs (make-hash-table)))
(defun make-bag (lst)
(if lst
(multiple-value-bind (val exists)
(gethash (car lst) hs)
(if exists
(setf (gethash (car lst) hs) (1+ val))
(setf (gethash (car lst) hs) 1))
(make-bag (cdr lst)))
hs)))
Now, if you try to evaluate this form twice, you will get answer doubled the second time:
(gethash 'x (make-bag '(x x x y y x z z z z x)))
> 5
> T
(gethash 'x (make-bag '(x x x y y x z z z z x)))
> 10
> T
Why did the answer doubled?
How to convert contents of a hash table to an assoc list?
Also note that recursive functions usually "eat" lists, and sometimes have an accumulator that accumulates the results of each step, which is returned at the end. Without hash-tables and ability of using remove-duplicates/count-if, logic gets a bit convoluted since you are forced to use basic functions.
Well, here's the answer, but to make it a little bit more useful as a learning exercise, I'm going to leave some blanks, you'll have to fill.
Also note that using a hash table for this task would be more advantageous because the access time to an element stored in a hash table is fixed (and usually very small), while the access time to an element stored in a list has linear complexity, so would grow with longer lists.
(defun make-bag (list)
(let (result)
(labels ((%make-bag (list)
(when list
(let ((key (assoc (car <??>) <??>)))
(if key (incf (cdr key))
(setq <??>
(cons (cons (car <??>) 1) <??>)))
(%make-bag (cdr <??>))))))
(%make-bag list))
result))
There may be variations of this function, but they would be roughly based on the same principle.