I am trying to write a function (lnn; list-not-nil) similar to list that only appends values that are not nil.
(list nil 3) --> (NIL 3)
(lnn nil 3) --> (3)
Here is the code I have so far. For some reason it causes infinite recursion on any input that I try.
(defun lnn (&rest items)
(lnn-helper nil items))
(defun lnn-helper (so-far items)
(cond ((null items)
so-far)
((null (car items))
(lnn-helper so-far (cdr items)))
(t (lnn-helper (append so-far (list (car items))) (cdr items)))))
Any ideas? Thanks very much.
(defun lnn-helper (so-far &rest items)
...)
With this argument list, items will never be nil if you always call lnn-helper with two arguments. Remove the &rest specifier, and it'll work.
Matthias' answer should have helped. Also note, that this is just a simple reduction:
(defun lnn (&rest elements)
(reduce (lambda (elt acc) (if elt (cons elt acc) acc))
elements
:from-end t
:initial-value nil))
Or even (less efficient):
(defun lnn (&rest elements)
(reduce #'cons (remove nil elements) :from-end t :initial-value nil))
Then:
(defun lnn (&rest elements)
(remove nil elements))
:)
P.S.: I know this was probably just an exercise in recursion, but SCNR.
Related
I'm working on a problem in a book where I have a binary tree and I need to check if the sum of all the atoms on the left and right subtree are equal and if they're not, return nil. I managed to do it in two functions but when I try to do it in one I get an error because it tries to add a number to nil.
The code is
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((/= (foo (cadr list))
(foo (caddr list))) nil)
( T (+ (foo (car list))
(foo (cdr list))))))
edit: the problem was two fold.
1) with the previous structure it would try to evaluate (cdr '(number)) so it would return null when it hit a list that looked like '(a (b c) d) since it would try to access (cdr '(d))
2) i used /= which only works if both arguments are numbers
The code that worked:
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((null (cdr list)) (car list))
((null (equal(foo (cadr list)) (foo (caddr list)))) nil)
(T (+ (car list)
(foo (cadr list))
(foo (caddr list))))))
After having defined how you represent a binary tree, I mean the right subtree could be the cdr or the cadr, I would separate the two problems:
(defun sum-of-subtree (tree)
(cond ((null tree) 0)
((atom tree) tree)
(t (+ (sum-of-subtree (car tree))
(sum-of-subtree (cdr tree))))))
(defun foo (tree)
(cond ((null tree) t) ;or whatever you want
((atom tree) t)
((= (sum-of-subtree (car tree))
(sum-of-subtree (cdr tree))) t)
(t nil)))
Like that, you will not be confusing the value of the sum of the subtree with the comparison. Other languages have stronger typing, which avoids mixing the purposes of different functions
Note: I'm assuming your binary trees are lists of (val left-sub right-sub), which seems to match your code.
I'm not sure that there's a clean way to do that with recursion and a single function, since the recursive process (summing the left and right subtrees) is different from the value your function needs to return (whether or not the left and right subtrees are equal).
However, if you absolutely have to solve it with one function, you could cheat a little. I see two options:
Option 1
Local function
(defun foo (list)
(labels ((sum-subtrees (list)
(cond
((null list) 0)
((atom list) list)
(t (+ (car list)
(sum-subtrees (cadr list))
(sum-subtrees (caddr list)))))))
(= (sum-subtrees (cadr list))
(sum-subtrees (caddr list)))))
This works by defining a local function to handle the recursive bit- #'sum-subtrees- and then just relies on that to compute the final output.
Option 2
Multiple value return
(defun foo (list)
(cond
((null list) (values t 0))
((atom list) (values t list))
(t (let ((left-sub (nth-value 1 (foo (cadr list))))
(right-sub (nth-value 1 (foo (caddr list)))))
(values (= left-sub right-sub)
(+ (car list)
left-sub
right-sub))))))
This solution exploits how common lisp functions can return multiple values. Basically, the function returns both the original condition (= left-subtree right-subtree) and the sum of the tree. Any other code which is expecting just a single value will get the first return value (the condition), so any code that would use this function should not notice the extra return value, but the data is there if you ask for it.
The way we return multiple values is with the values function. In this code, for example, we return (values t 0) in the case of list being nil to indicate that its "left and right subtrees" are equal and its sum is 0, and
(values (= left-sub right-sub)
(+ (car list)
left-sub
right-sub))
to produce the recursive return value.
There are a few ways to get access to the extra return values, but the one used here is #'nth-value, which returns the nth value returned instead of the first. That's why, when we make the recursive call to compute the size of the subtree, we use (nth-value 1 (foo <subtree>)).
NOTE: Please never actually use that solution for this- multiple value return is very useful and powerful, but in this case it is more confusing than it's really worth.
The code that worked:
(defun foo (list)
(cond ((null list) 0)
((atom list) list)
((null (cdr list)) (car list))
((null (equal(foo (cadr list)) (foo (caddr list)))) nil)
(T (+ (car list)
(foo (cadr list))
(foo (caddr list))))))
so I have a program:
(defun add (L)
(cond((endp L) nil)
(t(cons(1+(first L)))(add(rest L)))))
that will add 1 to each member of the list. I want to check if the list is all numbers and return nil if not, and don't know how to go about doing that within the defun.
I thought of doing
(defun add (L)
(cond((endp L) nil)
((not(numberp(first L))) nil)
(t(cons(1+(first L)))(add(rest L)))))
but that will still return the beginning of the list if the non number is in the middle. How would I pre check and return nil at the beginning?
You can wrap it in a condition-case
(defun add (L)
(condition-case nil
(mapcar '1+ L)
(error nil)))
Another possibility is to use iteration:
(defun add (l)
(loop for x in l
if (numberp x)
collect (1+ x)
else do (return-from add nil)))
The function is immediately exited with nil on the first non numeric element.
You would not implement iteration using recursion, since Lisp already provides iteration constructs. Example: MAPCAR.
Common Lisp also provides control flow constructs like RETURN-FROM, where you return from a block. A function defined by DEFUN has a block with its name and BLOCK can also create a named block explicitly. Examples for both:
CL-USER 62 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 nil 5 6)))
NIL
CL-USER 63 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 4 5 6)))
(2 3 4 5 6 7)
As function:
CL-USER 64 > (defun increment-list (list)
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from increment-list nil)))
list))
INCREMENT-LIST
CL-USER 65 > (increment-list '(1 2 3 4 5 6))
(2 3 4 5 6 7)
CL-USER 66 > (increment-list '(1 2 3 nil 5 6))
NIL
I'd say that an idiomatic way, in Common Lisp, of checking that all elements in a list are numbers would be (every #'numberp the-list), so I would probably write this as:
(defun add-1 (list)
(when (every #'numberp list)
(mapcar #'1+ list)))
It would be possible to use (if ...) or (and ...), but in this case I would argue that (when ...) makes for the clearest code.
The difficulty is that propagating nil results in the nil at the end of the list causing everything to be nil. One solution is to check that add returns nil but (rest xs) is not nil. However, IMO it is more straightforward to just iterate over the list twice, checking for numbers the first time and then doing the addition on the second iteration.
Try this:
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (let ((r (add (rest xs))))
(cond ((and (not r) (rest xs)) nil)
(t (cons (1+ (first xs)) r)))))))
Barring mistakes on my end, this results in:
(add '()) => nil
(add '(1 2)) => '(2 3)
(add '(x y)) => nil
(add '(1 2 y)) => nil
EDIT: Without let. This results in 2^(n+1)-1 calls to add for a list of length n.
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (cond ((and (not (add (rest xs))) (rest xs)) nil)
(t (cons (1+ (first xs)) (add (rest xs)))))))))
So I'm making this function in lisp, and in the cond part basically if a condition is met, I return a list with 2 values, and if the condition is not met, I would like to not return anything at all! Here it is:
(defun lista-dos-aprovados (turma)
(mapcar (lambda (aluno)
(cond ((> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno)))
(t nil)))
turma))
the names are in portuguese but I think it doesn't really matter here. What I'd like to do is when the code reaches the (t nil) part, I don't want it to write NIL inside my list. I tried not having the T condition or leaving it empty after the T, still it always writes NIL.
You can remove the nil in the result of mapcar, like in:
(defun lista-dos-aprovados (turma)
(remove nil
(mapcar (lambda (aluno)
(cond ((> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno)))
(t nil)))
turma)))
and note that you can simplify the function as:
(defun lista-dos-aprovados (turma)
(remove nil
(mapcar (lambda (aluno)
(when (> (media-notas (notas aluno)) 9.5)
(list (first aluno) (second aluno))))
turma)))
or you can use a loop:
(defun lista-dos-aprovados (turma)
(loop for aluno in turma
when (> (media-notas (notas aluno)) 9.5)
collect (list (first aluno) (second aluno))))
i worte this function to remove numbers from a list x
(defun rm-nums (x)
(cond
((null x) nil)
(t (mapcar 'numberp x))))
however when i enter (rm-nums '(32 A T 4 3 E))
returns (T NIL NIL T T NIL)
i want it instead of returning T or Nil, i want it to return the values that caused NIL only [which are not numbers]
so this example should return (A T E)
i am supposed to use mapcar WITHOUT recursion or iteration or the bultin function "remove-if"
i think it is related to something called apply-append but i know nothing about it. any help?
I think your course had this in mind:
(defun my-remove-if (pred lst)
(apply #'append (mapcar (lambda (x)
(and (not (funcall pred x))
(list x)))
lst)))
It does use apply and append and mapcar, like you said. Example usage:
(my-remove-if #'numberp '(32 a t 4 3 e))
=> (a t e)
More idiomatic solution suggested by Rörd:
(defun my-remove-if (pred lst)
(mapcan (lambda (x)
(and (not (funcall pred x))
(list x)))
lst))
i've seen several examples of implementing append an element to a list, but all are not using tail recursion. how to implement such a function in a functional style?
(define (append-list lst elem)
expr)
The following is an implementation of tail recursion modulo cons optimization, resulting in a fully tail recursive code. It copies the input structure and then appends the new element to it, by mutation, in the top-down manner. Since this mutation is done to its internal freshly-created data, it is still functional on the outside (does not alter any data passed into it and has no observable effects except for producing its result):
(define (add-elt lst elt)
(let ((result (list 1)))
(let loop ((p result) (lst lst))
(cond
((null? lst)
(set-cdr! p (list elt))
(cdr result))
(else
(set-cdr! p (list (car lst)))
(loop (cdr p) (cdr lst)))))))
I like using a "head-sentinel" trick, it greatly simplifies the code at a cost of allocating just one extra cons cell.
This code uses low-level mutation primitives to accomplish what in some languages (e.g. Prolog) is done automatically by a compiler. In TRMC-optimizing hypothetical Scheme, we would be able to write the following tail-recursive modulo cons code, and have a compiler automatically translate it into some equivalent of the code above:
(define (append-elt lst elt) ;; %% in Prolog:
(if (null lst) ;; app1( [], E,R) :- Z=[X].
(list elt) ;; app1( [A|D],E,R) :-
(cons (car lst) ;; R = [A|T], % cons _before_
(append-elt (cdr lst) elt)))) ;; app1( D,E,T). % tail call
If not for the cons operation, append-elt would be tail-recursive. This is where the TRMC optimization comes into play.
2021 update: of course the whole point of having a tail-recursive function is to express a loop (in a functional style, yes), and so as an example, in e.g. Common Lisp (in the CLISP implementation), the loop expression
(loop for x in '(1 2) appending (list x))
(which is kind of high-level specification-y if not even functional in its own very specific way) is translated into the same tail-cons-cell tracking and altering style:
[20]> (macroexpand '(loop for x in '(1 2) appending (list x)))
(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
(BLOCK NIL
(LET ((#:G3047 '(1 2)))
(PROGN
(LET ((X NIL))
(LET ((#:ACCULIST-VAR-30483049 NIL) (#:ACCULIST-VAR-3048 NIL))
(MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
(TAGBODY SYSTEM::BEGIN-LOOP (WHEN (ENDP #:G3047) (LOOP-FINISH))
(SETQ X (CAR #:G3047))
(PROGN
(LET ((#:G3050 (COPY-LIST (LIST X))))
(IF #:ACCULIST-VAR-3048
(SETF #:ACCULIST-VAR-30483049
(LAST (RPLACD #:ACCULIST-VAR-30483049 #:G3050)))
(SETF #:ACCULIST-VAR-30483049
(LAST (SETF #:ACCULIST-VAR-3048 #:G3050))))))
(PSETQ #:G3047 (CDR #:G3047)) (GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
(MACROLET
((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP)))
(RETURN-FROM NIL #:ACCULIST-VAR-3048)))))))))) ;
T
[21]>
(with the mother of all structure-mutating primitives spelled R.P.L.A.C.D.) so that's one example of a Lisp system (not just Prolog) which actually does something similar.
Well it is possible to write a tail-recursive append-element procedure...
(define (append-element lst ele)
(let loop ((lst (reverse lst))
(acc (list ele)))
(if (null? lst)
acc
(loop (cdr lst) (cons (car lst) acc)))))
... but it's more inefficient with that reverse thrown in (for good measure). I can't think of another functional (e.g., without modifying the input list) way to write this procedure as a tail-recursion without reversing the list first.
For a non-functional answer to the question, #WillNess provided a nice Scheme solution mutating an internal list.
This is a functional, tail recursive append-elt using continuations:
(define (cont-append-elt lst elt)
(let cont-loop ((lst lst)
(cont values))
(if (null? lst)
(cont (cons elt '()))
(cont-loop (cdr lst)
(lambda (x) (cont (cons (car lst) x)))))))
Performance-wise it's close to Will's mutating one in Racket and Gambit but in Ikarus and Chicken Óscar's reverse did better. Mutation was always the best performer though. I wouldn't have used this however, but a slight version of Óscar's entry, purely because it is easier to read.
(define (reverse-append-elt lst elt)
(reverse (cons elt (reverse lst))))
And if you want mutating performance I would have done:
(define (reverse!-append-elt lst elt)
(let ((lst (cons elt (reverse lst))))
(reverse! lst)
lst))
You can't naively, but see also implementations that provide TCMC - Tail Call Modulo Cons. That allows
(cons head TAIL-EXPR)
to tail-call TAIL-EXPR if the cons itself is a tail-call.
This is Lisp, not Scheme, but I am sure you can translate:
(defun append-tail-recursive (list tail)
(labels ((atr (rest ret last)
(if rest
(atr (cdr rest) ret
(setf (cdr last) (list (car rest))))
(progn
(setf (cdr last) tail)
ret))))
(if list
(let ((new (list (car list))))
(atr (cdr list) new new))
tail)))
I keep the head and the tail of the return list and modify the tail as I traverse the list argument.