I am trying to write an fx in lisp to tell if an object ends in nil.
(setq isList (lambda (listOfValues)
(if (null listOfValues) t)
( funcall isList (cdr listOfValues) )
)
)
However, I am having trouble checking if its nil in all cases. In particular, cdr would fail at last elt if it is not a list. How can I resolve this?
Before we get closer to answer your actual question, a few things. First, use defun to define functions, not "set a variable to a lambda", it will make you happier down the line. Second, Common Lisp style would vale been one of values, list-of-values, or just list (that would indicate we knew it was a list, so I would probably just have gone with values here), not "listOfValues" (case is typically smashed, and neither "listofvalues" nor "LISTOFVALUES" are easy to read).
So, back to the code. A list is composed of cons cells, of either atoms or other cons cells. We have two test functions, either consp or atom that would be useful in this case. We know that if we're looking at a cons, we need to recurse on its cdr, otherwise we're at the last element and can just check if we're looking at nil.
(defun is-proper-list (values)
(if (consp values)
(is-proper-list (cdr values))
(null values))) ;; We could do this test as (eql nil) as well
It can be done faster with
(defun listp (l)
(tailp nil l))
(tailp nil ...) tests, whether nil is the end of a given object after cdr-ing to the end.
tailp is a very special function. So don't use it without understanding it.
(tailp '(b c) '(a b c)) is e.g. NOT T, because '(b c) is not the same object like the ( ... b c). But in this case, because NIL is '() and is unique in Lisp, any nil is object-identical. Therefore one can use tailp here for this specific test, whether a given list ends with NIL.
listp is a lisp-convention conform name for this.
(predicate functions returning booleans ending with p for predicate.
Since no - used in the name, attach p without - otherwise attach -p).
(tailp (cdr '(a b c)) '(a b c)) ;; NIL
;; because the two lists are not object-identical
(setq l '(a b c))
(tailp (cddr l) l) ;; T ;; object-identical
Related
I have a code which takes a list and returns all possible permutations by the parameter result.
But when I compile I have an error which says *** - =: (1+ INDEX) is not a number.
Is this message true or I messed up the code generally?
I am new to lisp I can looking for a fix and also open to suggestions from fucntional programmers.
;; Creates permutatiions of a given list and returns it via parameter
(defun create-permuations (source)
(setf result (list))
(create-permuations-helper source 0 '() result)
result)
(defmacro create-permuations-helper (source index cur result)
(if (= (list-length cur) index)
(cons cur result)
(loop for i from 0 to (list-length cur) do
(create-permuations-helper source (1+ index)
(append cur (list (nth i source))) result))))
99% of times when a compiler reports an error you can trust it to be true. Here Index is the list (1+ index), literally the 1+ symbol followed by the index symbol. This is so because you are using a macro, and macros operate on code.
In your macro, you do not return a form to be evaluated, you execute code during macro-expansion that depends on itself. That alone is an undefined behaviour. For example:
(defmacro a (x)
(if (plusp x)
(a (- x 1))
nil))
In the body of a, you want to expand code using a recursive call to itself. But the macro is not yet fully known and cannot be until the whole macro is defined.
Maybe the particular lisp implementation binds a to the macro function in body of the macro, which is a strange thing to do, or you evaluated the definition twice. The first time the compiler assumes a is an unknown function, then binds a to a macro, and the second time it tries to expand the macro.
Anyway macro are not supposed to be recursive.
In the example, since the macro does not evaluate its argument, the nested call to the macro is given the literal expression (- x 1), and not its actual value, which cannot be known anyway since x is unknown. You are crossing a level of abstraction here by trying to evaluate things at macroexpansion time.
But, macros can expand into code that refers to themselves.
(defmacro a (x)
(if (plusp x)
`(b (a ,(- x 1)))
nil))
Now, (a 2) expands into (b (a 1)), which itself macroexpands into (b (b (a 0))), and finally reaches a fixpoint which is (b (b nil)).
The difference is that the macro produces a piece of code and returns, which the compiler macroexpands again, whereas in the first example, the macro must already be expanded in the body of its own definition.
Possible implementation
One way to solve your problem is to define a local function that has access to a variable defined in your main function. Then, the local function can set it, and you do not need to pass a variable by reference (which is not possible to do):
(defun permut (list)
(let (result)
(labels ((recurse (stack list)
(if list
(dolist (x list)
(recurse (cons x stack)
(remove x list :count 1)))
(push stack result))))
(recurse nil list))
result))
Alternatively, you can split the process in two; first, define permut-helper, which is a higher-order function that takes a callback function; it generates permutations and calls the callback for each one:
(defun permut-helper (stack list callback)
(if list
(dolist (x list)
(permut-helper (cons x stack)
(remove x list :count 1)
callback))
(funcall callback stack)))
You call it with a function that pushes results into a list of permutations:
(defun permut (list)
(let (result)
(flet ((add-result (permutation)
(push permutation result)))
(permut-helper nil list #'add-result))
result))
I am trying to evaluate each atom of a list and see if it's equal to the number provided and remove if its not but I am running into a slight problem.
I wrote the following code:
(defun equal1(V L)
(cond((= (length L) 0))
(T (cond( (not(= V (car(equal1 V (cdr L))))) (cdr L) )))
)
)
(equal1 5 '(1 2 3 4 5))
I obtain the following error
Error: Cannot take CAR of T.
If I add (write "hello") for the action if true, the following error is obtained:
Error: Cannot take CAR of "hello".
I'm still quite new to LISP and was wondering what exactly is going on and how could I fix this so I could evaluate each atom properly and remove it if its not, thus the cdr L for the action.
car and cdr are accessors of objects of type cons. Since t and "hello" are not cons you get an error message.
To fix it you need to know what types your function returns and not car unless you know that it's a cons
EDIT
First off ident and clean up the code.. The nested cond are uneccesary since cond is a if-elseif-else structure by default:
(defun remove-number (number list)
(cond ((= (length list) 0)
t)
((not (= number (car (remove-number number (cdr list)))))
(cdr list))))
(t
nil)))
I want you to notice I've added the default behaviour of returning t when a consequent is not given as we know = returns either t or nil so it returns t when the length is 0 in this case.
I've added the default case where none of the two previous predicates were truthy and it defaults to returning nil.
I've named it according to the functions used. = can only be used for numeric arguments and thus this will never work on symbols, strings, etc. You need to use equal if you were after values that look the same.
Looking at this now we can see that the functions return value is not very easy to reason about. We know that t, nil and list or any part of the tail of list are possible and thus doing car might not work or in the case of (car nil) it may not produce a number.
A better approach to doing this would be:
check if the list is empty, then return nil
check if the first element has the same numeric value as number, then recurse with rest of the list (skipping the element)
default case should make cons a list with the first element and the result fo the recursion with the rest of the list.
The code would look something like this:
(defun remove-number (number list)
(cond ((endp list) '())
((= (car list) number) (remove-number ...))
(t (cons ...))))
There are a couple of things you could do to improve this function.
Firstly, let's indent it properly
(defun equal1 (V L)
(cond
((= (length L) 0))
(T (cond
((not (= V (car (equal1 V (cdr L))))) (cdr L))))))
Rather than saying (= (length l) 0), you can use (zerop (length l)). A minor sylistic point. Worse is that branch returns no value. If the list L is empty what should we return?
The issue with the function is in the T branch of the first cond.
What we want to do is
remove any list item that is the same value as V
keep any item that is not = to V
The function should return a list.
The expression
(cond
((not (= V (car (equal1 V (cdr L))))) (cdr L)))
is trying (I think) to deal with both conditions 1 and 2. However it's clearly not working.
We have to recall that items are in a list and the result of the equal function needs to be a list. In the expression above the result of the function will be a boolean and hence the result of the function call will be boolean.
The function needs to step along each element of the list and when it sees a matching value, skip it, otherwise use the cons function to build the filtered output list.
Here is a skeleton to help you out. Notice we don't need the embedded cond and just have 3 conditions to deal with - list empty, filter a value out, or continue to build the list.
(defun equal-2 (v l)
(cond
((zerop (length L)) nil)
((= v (car l)) <something goes here>) ;skip or filter the value
(t (cons (car l) <something goes here>)))) ;build the output list
Of course, this being Common Lisp, there is a built-in function that does this. You can look into remove-if...
I'm working through The Elements of Artificial Intelligence Using Common Lisp by Steven Tanimoto and I can't figure out his match program. So far the idea is to gradually improve upon a self-rolled list match, starting with not very good
(defun match1 (p s) (equalp p s))
Here's match3:
(defun match3 (p s)
(cond
((null p) (null s)) ;null clause
((or (atom p) (atom s)) nil) ;atom clause
((equalp (first p) (first s)) ;equal CAR clause
(match3 (rest p) (rest s)))
((eql (first p) '?) ; joker clause
(match3 (rest p) (rest s)))
(t nil))) ;extremal clause
the so-called joker clause should match, i.e.,
(match3 '(a b ? d) '(a b c d)) ; yields t
but then the next version should "match" this
(match4 '((? x) b c (? y)) '(a b c d))
I quote
This would permit, for example, the (above) form to not only return
true, but also return the association of a with x and the
association of d with y. In that way, if the match is used as a
condition in a production rule, the action part of the rule can
manipulate the values matching the variable elements in the pattern.
...and then it goes on talking about alist things. Then the rewrite of match:
(defun4 match4 (p s)
(cond
((and (null p) (null s))
'((:yes . :yes)))
((or (atom p) (atom s)) nil)
((equalp (first p) (first s))
(match4 (rest p) (rest s)))
((and
(equalp (length (first p)) 2)
(eql (first (first p)) '?)
(let ((rest-match
(match4 (rest p) (rest s))))
(if rest-match
(acons (first (rest (first p)))
(first s)
rest-match)))))
(t nil)))
...so if someone could get me started by first telling me why we want to compare (? x) to a in the example above, that would help. Basically, I'm not clear on what the goal is here. If someone could explain the motivation behind this, I think I could pick apart the code. Otherwise, I'm totally lost.
match3 introduces simple pattern matching between two lists, where the symbol ? in the first list can match any single symbol in the second list. For this reason the function returns T or NIL, to denote the success or the failure of the matching process.
Then a new kind of match is introduced in match4, through the use of what appear to be a match variable. (? x) is simply a way of introducing a match variable, that in other languages could be written as ?x, or something similar. The idea is that this variable “captures” the symbol matched on the second list, so that, for instance, you could later use it in a way similar to this:
(match '(a (? x) (? y) (? x) b) '(a c d c b)) ; yes, since ‘c’ matches ‘?x’
(match '(a (? x) (? y) (? x) b) '(a c d e b)) ; no, since ‘c’ and ‘e’ are different
For this to be used effectively, the function match must give, when a match is found, not simply the value T, but the couple (match variable, symbol matched), and build with it an associative list of matches found. So, match4 returns such list through the use of acons, in the last branch of the cond (first it gets rest-match, than “aconses” over it the pair given by the match variable and the symbol found). The special pair (:yes . :yes) is simply a way of terminating this list of matches.
I suppose that later in the book will be presented another version of the match function in which the matches found will be used in the subsequent part of the process.
I have tanimoto's book, but won't have access to it until tomorrow at the earliest, but the example mentioned in the quote is actually a good one:
in that way, if the match is used as a condition in a production rule, the action part of the rule can manipulate the values matching the variable elements in the pattern.
Production rule systems are a good example of where this kind of matching is useful. It lets rule writers focus on domain knowledge, and to keep algorithms for processing rules separate.
Some approaches to functional programming also make heavy use of pattern matching. Programing language support varies, though. Common Lisp makers it easy to wrote your own though.
I want my function to print each item in the list and sublist without quotes and return the number of items. The output of the list also needs to be in order, but my function is printing in reverse. I'm not sure why, is there any reasons why? Any suggestions to how I can recursively count the number of items and return that number? In addition why is the last item printed is supposed to be 9.99 instead of 100.999?
Edit: Thanks for the help so far. Just last question: Is there a way to make any output like DAY to be in lower case (day), or is that something that can't be done?
My function:
(defun all-print (inlist)
(cond
((not (listp inlist))
(format t "Error, arg must be a list, returning nil")
())
((null inlist) 0)
((listp (car inlist))
(ffn (append (car inlist)(cdr inlist))))
(t
(format t "~a " (car inlist) (ffn (cdr inlist))))))
My output example:
CL-USER 1 > (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
100.999 -5.9 DAY -10 9 3 night 5
NIL
What it's suppose to output example:
5 night 3 9 -10 day -5.9 9.99 ;print
8 ;returns
It looks like all-print is supposed to be called ffn, since it looks like those are supposed to be recursive calls. In the rest of this answer, I'm just going to use ffn since it's shorter.
Why the output is in reverse
At present, your final cond clause makes the recursive call before doing any printing, because your recursive call is an argument to format:
(format t "~a " (car inlist) (ffn (cdr inlist)))
; ------------ -----------------
; 3rd 4th
All the arguments to format, including the 4th in this case, are evaluated before format is called. The 4th argument here will print the rest of the list, and then format will finally print the first element of the list. Your last cond clause should do the printing, and then make the recursive call:
(cond
…
(t
(format t "~a " (car inlist))
(ffn (cdr inlist))))
Why you get 100.999 rather than 9.99
You're getting 100.999 in your output rather than 9.99 (or something close to it) because the value of (* 100.999) is simply the value of 100.999. I'm guessing that you wanted (* 10 0.999) (note the space between 10 and 0.99). That still won't be quite 9.99 because of floating point arithmetic, though, but it will be close.
How to get the number of elements printed
uselpa's answer provides a good solution here. If you're supposed to return the number of elements printed, then every return value from this function should be a number. You have four cases,
not a list — returning nil is not a great idea. If this can't return a number (e.g., 0), then signal a real error (e.g., with (error "~A is not a list" inlist).
inlist is empty — return 0 (you already do)
(car inlist) is a list — here you make a recursive call to ffn. Since the contract says that it will return a count, you're fine. This is one of the reasons that it's so important in the first case (not a list) that you don't return a non-number; the contract depends on every call that returns returning an number.
In the final case, you print one item, and then make a recursive call to ffn. That recursive call returns the number of remaining elements that are printed, and since you just printed one, you need to add one to it. Thus the final cond clause should actually be something like the following. (Adding one to something is so common that Common Lisp has a 1+ function.)
(cond
…
(t
(format t "~a " (car inlist))
(1+ (ffn (cdr inlist))))) ; equivalent to (+ 1 (ffn (cdr inlist)))
A more efficient solution
We've addressed the issues with your original code, but we can also ask whether there are better approaches to the problem.
Don't append
Notice that when you have input like ((a b c) d e f), you create the list (a b c d e f) and recurse on it. However, you could equivalently recurse on (a b c) and on (d e f), and add the results together. This would avoid creating a new list with append.
Don't check argument types
You're checking that the input is a list, but there's really not much need to do that. If the input isn't a list, then using list processing functions on it will signal a similar error.
A new version
This is somewhat similar to uselpa's answer, but I've made some different choices about how to handle certain things. I use a local function process-element to handle elements from each input list. If the element is a list, then we pass it to print-all recursively, and return the result of the recursive call. Otherwise we return one and print the value. (I used (prog1 1 …) to emphasize that we're returning one, and printing is just a side effect. The main part of print-all is a typical recursion now.
(defun print-all (list)
(flet ((process-element (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x)))))
(if (endp list)
0
(+ (process-element (first list))
(print-all (rest list))))))
Of course, now that we've pulled out the auxiliary function, the iteration is a bit clearer, and we see that it's actually a case for reduce. You might even choose to do away with the local function, and just use a lambda function:
(defun print-all (list)
(reduce '+ list
:key (lambda (x)
(if (listp x)
(print-all x)
(prog1 1
(format t "~A " x))))))
Here's my suggestion on how to write this function:
(defun all-print (lst)
(if (null lst)
0 ; empty list => length is 0
(let ((c (car lst))) ; bind first element to c
(if (listp c) ; if it's a list
(+ (all-print c) (all-print (cdr lst))) ; recurse down + process the rest of the list
(progn ; else
(format t "~a " c) ; not a list -> print item, then
(1+ (all-print (cdr lst)))))))) ; add 1 and process the rest of the list
then
? (all-print (list 5 "night" 3 (list 9 -10) (quote day) -5.9 (* 100.999)))
5 night 3 9 -10 DAY -5.9 100.999
8
I want to make a function that checks if an element is a member of a list. The list can contain other lists.
This is what I came with so far:
(defun subl(l)
(if (numberp l)
(if (= l 10)
(princ "Found"))
(mapcar 'subl l)))
Now the number I am searching for is hard-coded and it is 10. I would like to write it somehow so the function takes another parameter(the number I am searching for) and returns true or 1 when it finds it. The main problem is that I can't see a way to control mapcar. mapcar executes subl on each element of l, if l si a list. But how can I controll the returned values of each call?
I would like to check the return value of each subl call and if one of it is true or 1 to return true or 1 till the last recursive call. So in the end subl returns true or one if the element is contained in the list or nil otherwise.
Any idea?
This procedure below should process as you have described;
(defun member-nested (el l)"whether el is a member of l, el can be atom or cons,
l can be list of atoms or not"
(cond
((null l) nil)
((equal el (car l)) t)
((consp (car l)) (or (member-nested el (car l))
(member-nested el (cdr l))))
(t (member-nested el (cdr l)))))
mapcar is a very generic primitive to map a function over a list. You can use one of the built-in combinators which are much more closely suited with what you're trying to do. Look into the member function.
Your function seems to play the role of main function and helper at the same time. That makes your code a lot more difficult to understand than it has to be..
So imagine you split the two:
;; a predicate to check if an element is 10
(defun number10p (l)
(and (numberp l)
(= l 10)))
;; the utility function to search for 10 amongst elements
(defun sublistp (haystack)
(mapcar #'number10p haystack)))
But here when you do (sublistp '(5 10 15 20)) you'll get (nil t nil nil) back. Thats because mapcar makes a list of every result. For me it seems you are describing some since it stops at the first true value.
(defun sublistp (haystack)
(some #'number10p haystack)))
(sublistp '(5 10 15 20)) ; ==> t
Now to make it work for any data type we change the predicate and make it as a local function where we have the argument we are searching for:
(defun sublistp (needle haystack)
(flet ((needlep (x)
(equal x needle)))
(some #'needlep haystack)))
(sublistp '(a b) '(a b c (a b) d e f)) ; ==> t
You can also do this with an anonymous predicate like this:
(defun sublistp (needle haystack)
(some #'(lambda (x)
(equal x needle))
haystack))
An implementation of this is the member function, except it returns the match as truth value. That's ok since anything but nil is true in CL:
(member 10 '(5 10 15 20)) ; ==> (10 15 20)
EDIT
You commented on a different answer that you are required to use mapcar in that case use it together with append to get a list of all matches and check if the list has greater than 0 elements:
(defun sublistp (needle haystack)
(flet ((needle-check (x)
(if (equal x needle) '(t) nil)))
(< 0 (length
(apply #'append
(mapcar #'needle-check haystack))))))
How it works is that for each match you get a list of one element and for every non match you get an empty list. When appending the lists you'll get the empty list when there is not match. For all other results you have a match. This is not a very efficient implementation.