Hi I am trying to remove unwanted variables from my list.
This is my function:
(defun remove-vars (list)
(loop for x in list do
(print x))))
I want to pass in this (get-vars '(A (NOT B) C))
and print out
A
B
C
but instead I am printing out
A
(NOT B)
C
Nil
is there a way to remove the parenthesis and the not from the list? Any guidance would be appreciated if the list was bigger with a b c d i would like to remove all instances of not and parenthesis. I guess what pseudocode would be to loop through check if "( ) or not exist in x" then delete those from the list
A simple solution is flatten the list and remove the NOT's like this:
(defun flatten (var-list)
(cond ((null var-list) nil)
((atom var-list) (list var-list))
(t (mapcan #'flatten var-list))))
(defun get-vars (var-list)
(remove 'NOT (flatten var-list)))
(get-vars '(A (NOT B) C))
Hope it helps
Your current code loops through and prints each element of the list, unconditionally.
When you pass it (A (NOT B) C), it is printing every element, one of which is the list (NOT B), and the loop is printing that list. The parentheses are output by the printer to represent that the element being printed is a list.
You need some logic to check if each element is something you'd like to not print, like the symbol NOT or nil, and recurse down when you see a something you want to examine further, such as a list.
Related
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
I don't understand the following paragraph:
(COUNT-ATOMS ’(A (B) C)) should return five.
A, B, and C and two NILs in the tree.
Write a function COUNT-ATOMS that returns the number of atoms in a tree.
I tried this:
(defun count-atoms(l)
(cond
((null l) 0)
(t (+ (cond
((atom (car l)) 1)
(t 0))
(count-atoms (cdr l))))))
However, (COUNT-ATOMS '(A (B) C)) return 2.
How should I do to return 5 instead?
Could you explain in more details?
If you wanted to build (a (b) c) at runtime, using only cons and quote, you would write:
(cons 'a
(cons (cons 'b nil)
(cons 'c nil)))
There are 5 atoms (a, b, c and two nil) in the tree being built. In practice you could use a simpler notation, like (list 'a (list 'b) 'c).
In your function, you do not recurse into the CARS of your trees, only the CDRS. Also, when the CAR is not an atom, like when you encounter (B), you add zero (the default clause in the second cond) (edit. As kmkaplan noted, you also count zero for nil, first cond).
A simple solution is this, based on typecase:
(defun count-atoms (form)
(typecase form
(atom 1)
(cons (+ (count-atoms (car form))
(count-atoms (cdr form))))))
When you encounter an atom, the result is 1.
When you have a cons cell, you sum the number of atoms in its car and cdr.
The typecase dispatches according to the type of its argument, here form. Each clause has the following syntax: (type ...body...), where type is the name of a type and ...body... one or more expressions (an implicit progn): the last value is the return value of the typecase, if the argument matches the type type.
The first clause (atom 1) says: if form is an atom, return 1. The following one, (cons ...) says: else, if form is a cons cell, .... Here, atom is the name of a type, which represents everything that is not a cons. Granted, once you know that something is not an atom, you know that it is necessarily a cons, and the second test is redundant. However, it is more readable and any decent compiler will optimize the second test away.
There is also a function named atom, which is a predicate that tests whether a value is an atom. That's why, when you write (atom 1) on its own, in the REPL, it returns T.
See also wikipedia and Seibel's Practical Common Lisp's chapter about lists.
Your function has two problems. The first, neatly described in coredump's answer, is that your COUNT-ATOMS only recurse on the tail (CDR) and forget to recurse on the CAR element of your cons cell (L). Thus it fails to count the B atom.
The second problem is that you count NIL as 0 while it is an atom and should be counted as 1.
I have to write a program in Lisp that returns the first item of a list if it contains an even number of elements, and the last if it contains an odd number of elements. I need a little advice on where to start? I don't need whole program.
You can get the length of a list with length.
(length '(a b c)) ;; 3
You can then go and check that number against the predicate function evenp, which returns T or NIL depending on if the argument is even or not.
(evenp 1) ;; NIL
(evenp 2) ;; T
The function first returns the first element of a list.
(first '(a b c)) ;; A
The function last returns the last cons of a list, so you'll have to unwrap the value using FIRST.
(last '(a b c)) ;; (C)
(first (last '(a b c))) ;; C
You could then combine these into a function like so:
(defun get-first-if-even-length (list)
(if (evenp (length list))
(first list)
(first (last list))))
This function returns the first or the last element in the list, depending if its length is even or not.
I'm not getting this first/last thing in Common-Lisp. Yes, I see how it works, but I don't get WHY it works that way.
Basically, to get the first item in a list, I can use (first mylist). However, if I want the last item, (last mylist) doesn't give me that; instead, it gives me a list containing the last item in my list!
(I'm using Clozure-CL, which has a few other oddities that seem like bugs to me but, since I'm a Lisp-n00b, I'm trying not to fall for the old "the interpreter is broken!" trick :) )
So, for example:
? (setq x '((1 2) (a b)))
=> ((1 2) (A B))
? (first x)
=> (1 2) ; as expected
? (last x)
=> ((A B)) ; why a list with my answer in it?!
? (first (last x))
=> '(A B) ; This is the answer I'd expect from plain-old (last x)
Can someone help me understand why last does this? Am I using these items incorrectly? Is first really the odd-ball?!
Thanks!
In Common Lisp last is supposed to return a list, from the documentation:
last list &optional n => tail
list---a list, which might be a dotted list but must not be a circular list.
n---a non-negative integer. The default is 1.
tail---an object.
last returns the last n conses (not the last n elements) of list. If list is (), last returns ().
For example:
(setq x (list 'a 'b 'c 'd))
(last x) => (d)
And yes, this is counterintuitive. In other flavors of Lisp it works as the name suggests, for example in Racket (a Scheme dialect):
(define x '((1 2) (a b)))
(first x) => '(1 2)
(last x) => '(a b)
(define x (list 'a 'b 'c 'd))
(last x) => 'd
Returning the last element is not very useful except to access the last element; returning the last cons lets you do something like this:
(let ((x (list 1 2 3)))
(setf (cdr (last x)) '(4))
x)
=> '(1 2 3 4)
while you can still access the last element as (car (last x)).
Common Lisp's misnamed function last gives you the last cons.
It should probably be called tail, as there is a function tailp, but my guess is that this name stuck for historical/compatibility reasons.
Generally, it gives you the nth tail of a list, or the nth cons before the end of the list.
This is just the way it is. first and last are not a complementary pair of operations. last is more closely related to rest and nthcdr. There is also butlast which constructs a new list that omits the last item from the given list.
first versus last is nothing compared to how get and getf have nothing to do with set and setf.
I have some problem using accessor function nth. I pass a list to some function and make new binding to an element of the list in the function with nth, then when I call the list out of the function, it is modified, and it's not what I want! What happens?
Some examples
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1
I understand what's going on above, but if we change everything to lists, something happens that I can't understand
(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)
I expected a to be (1), why it has been modified? I also tried other functions like car and first, result is the same.
PS, I tried it in Lispworks and SBCL, same result.
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1
You pass 1 to test. Within test you modified the local variable x. a is not changed and can't be changed that way - we pass the value of a not a reference to a.
(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)
You pass the list (1) to test. The list is not copied. The local variable x points to the first cons cell in the list. You then modify the car of the first cons cell to 2. Since the list is not copied, you modify the passed list. a also points to the first cons cell of that list. So it is also (2).
If you don't want anything to be modified, don't use incf. Use 1+. The only reason to use incf is because you want its side-effect.
As to why this is happening, arguments are evaluated before being passed to a function. When you call test with a being 1, you are passing the value 1, which cannot be modified. When a resolves to a list, you are passing a list, which can be setf'd all over the shop, if you've chosen to use destructive functions.
See the documentation on nth. nth returns a place that setq can then operate on.
nth may be used to specify a place to setf. Specifically,
(setf (nth n list) new-object) == (setf (car (nthcdr n list)) new-object)