I am new to LISP and was wondering how to return a list from a function.
I need to write a function that takes a list as an input and outputs a list.
If first and last elements are even numbers:
return a list with first ** 2 and last ** 4
else
return a list with first and last elements
How do I return a list correctly?
(defun test (elements)
(if (and (numberp (nth 0 elements))
(numberp (last elements)))
(if (and (evenp (nth 0 elements))
(evenp (last elements)))
(return from test (list (expt (last elements) 2) (expt (nth 0 elements) 4)))
)
)
(return from test (list (nth 0 elements) (last elements)))
)
Example:
(cond ((foo-p n) (list 1 2)) ; returns the list
((bar-p m) (list 3 4)) ; returns the list
(t (list 5 6))) ; returns the list
or
(if (foo-p n)
(list 1 2) ; returns the list
(if (bar-p m)
(list 3 4) ; returns the list
(list 5 6))) ; returns the list
A list is a chain of pairs. eg. (1 2 3) is created with (cons 1 (cons 2 (cons 3 '()))). If you know this in your heart it will be much easier to do list processing.
Because of the structure fo a list a list is created from end to beginning and iterated from beginning to end.
Eg. replacing first element is easy. You (cons (do-something (car elements)) (cdr elements)) and you have a list with the first element changed. You could do the same with (reverse elements) to alter the last element before reversing it again. Put these two together and you have a solution.
No return is necessary. eg. if the body if a function is as follows the argument will get a new element in the beginning if some-expr is truthy and the argument if it is not.
(if some-expr
(cons 3 elements)
elements)
Every part of lisp works like this. An expression can be seen as computing a returned value. eg. some-expr returns a value that is evaluated by if. Eg. it's not the function scope you are exiting, but each level of an expression as well.
Related
I have a function that doubles every item in a list:
(defun double (L)
(cond
((atom L) nil)
(t (cons (car L) (cons (car L ) (double (cdr L))))) ) )
(double '(a b c )) => (a a b b c c)
How could I accomplish the same result while dividing by 2 the number of times the function calls cons ? (i.e. in the previous example, it calls cons 6 times. How could I do it with 3 times only?)
Thanks!
Edit 2, after jkiiski's comments, seems like it works now:
(defun double2 (L)
(cond
((atom L) nil)
(t (setf
(cdr L)
(cons (car L ) (double2 (cdr L))))
L) ) )
(double2 (list 'a 'b 'c)) => (a a b b c c)
Here is an another way of doing it, without recursion. Note that this answer assumes you are doing a homework and trying to find a way to avoid creating a fresh list, which is what the simplest solution does. In practice, you would simply use collect twice in a loop, like Sylwester demonstrated. Here the original input list is destructively modified.
Copy list
Suppose your original list is (1 2 3). Instead of consing
elements yourself, you can call (copy-list list), which performs the
required amount of consing. That's all you need to consider for memory
allocation. Then, you "only" need to interleave all the cons cells to
obtain the desired repetition.
Keep the list variable as given, and define two variables which
iterate over both lists:
current = (1 2 3) ;; original
fresh = (1 2 3) ;; copy
Reordering cells
Graphically, you want to change CDRs to "thread" existing cons-cells together. At first, both lists look like this:
current ( 1 . x-)-->( 2 . x-)-->...
fresh ( 1 . x-)-->( 2 . x-)-->...
But you want to have:
current ( 1 . x ) ( 2 . x )
| ^ |
V | V
fresh ( 1 . x ) ( 2 . ...)
More formally, at the beginning of each step, and when your lists are not empty, the above variables can be decomposed as follows:
current = (chead . ctail)
fresh = (fhead . ftail)
You want to make current's tail point to the fresh cons-cell, and make fresh's tail point to ctail.
Once you finish interleaving cells, the variables should be bound as follows:
current = (chead . (fhead . ctail))
fresh = ftail
And then, you can descend twice in current, so that finally:
current = ctail
fresh = ftail
From here, you can continue with the rest of both lists. Note that
list still contains the original cons cell you were given as an
input.
Code
(defun double-loop (list)
(loop
with fresh = (copy-list list) ;; cursor to new cons cells
with current = list ;; cursor to current cell
while fresh ;; stop when fresh is nil
do (print (list list current fresh)) ;; for debugging
(rotatef (cdr fresh) (cdr current) fresh) ;; change CDRs, rebind fresh
(setf current (cddr current)) ;; update CURRENT
finally (return list))) ;; LIST points to head of result
I am using ROTATEF to wire cons cells:
(rotatef (cdr fresh) (cdr current) fresh)
What happens is that the value of fresh is placed in (cdr current), whose previous value is itself placed in (cdr fresh), the original
value of which eventually becomes the new value bound to fresh.
Example
Here is an example trace output:
CL-USER> (double-loop (list 0 1 2 3))
((0 1 2 3) (0 1 2 3) (0 1 2 3))
((0 0 1 2 3) (1 2 3) (1 2 3))
((0 0 1 1 2 3) (2 3) (2 3))
((0 0 1 1 2 2 3) (3) (3))
=> (0 0 1 1 2 2 3 3)
After jkiiski's comments, seems like it works now:
(defun double2 (L)
(cond
((atom L) nil)
(t (setf
(cdr L)
(cons (car L ) (double2 (cdr L))))
L) ) )
(double2 (list 'a 'b 'c)) => (a a b b c c)
I'm new Lisp programmer and need some help.
Given a list, I`m trying to copy elements that appear once in another list.
I have done the following:
(defun Unique-elements ( l uniqueList )
(or (null l)
(and (not (member (car l) (cdr l)))
(Unique-elements (cdr l)))))
The function returns True if the supplied list contains distinct items. How to copy the distinct items in uniqueList and show it.
Example:
Given List:
(1 2 3 4 4 5 6 6 7 8 8 8 8)
Expected Result:
(1 2 3 5 7)
That would be a working function for the original problem:
(defun has-only-unique-elements-p (l)
(or (null l)
(and (not (member (car l) (cdr l)))
(has-only-unique-elements-p (cdr l)))))
If you want to return the unique elements you need to write it differently. A naive algorithm:
if l is empty return NIL
if the first element is in the rest list, remove the element and call the function recursively
otherwise cons the first element to the result of the recursive call with the rest list
I am trying to write a function in Racket that will reverse the order of pairs. For example, given the list '(1 2) the function should produce '(2 1). Here is my code so far:
(define (reverse aList)
(cons (second aList)
(first aList))
This is not producing the correct answer, however. When I test with '(a b) it returns '(b . a) instead of '(b a). How do I get rid of the period between the b and a?
You should have:
(define (reverse-pair lst)
(cons (second lst) (cons (first lst) empty)))
As stated in Racket's docs:
The cons function actually accepts any two values, not just a list for the second argument. When the second argument is not empty and not itself produced by cons, the result prints in a special way. The two values joined with cons are printed between parentheses, but with a dot (i.e., a period surrounded by whitespace) in between.
So,
> (cons 1 2)
'(1 . 2)
> (cons 1 (cons 2 empty)) ; equivalent to (list 1 2)
'(1 2)
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.
So I'm new to LISP, and I'm playing with a couple of basic sum functions.
(defun suma (&rest L)
(cond
((null L) 0)
(T (+ (CAR L) (EVAL (CONS 'suma (CDR L)))))
))
(defun suma2 (&rest L)
(cond
((null L) 0)
(T (+ (car L) (suma2 (cdr L))))
))
The first function works just fine. The second function gives this error: SB-KERNEL::CONTROL-STACK-EXHAUSTED.
My question is: why is the first function ok and the second is not when they are essentially doing the same thing?
If you call, say, (suma2 1 2 3), L will be the list (1 2 3). You will then call (suma2 (cdr L)), i.e. (suma2 '(2 3)). In that invocation L will be the list ((2 3)), i.e. a list containing a single element: the list (2 3). Now it will call (suma2 (cdr L)) again and this time (cdr L) is the empty list, so in the next invocation L is a list containing the empty list. Since that's still a list containing one element, it will again recurse and again and again. The case where L is empty will never be reached because L will always be a list containing exactly one element: the result of (cdr L).
So you should either change your suma2 function to accept a list instead of a variable number of arguments (and then call it as (suma2 (list 1 2 3)) or (suma2 '(1 2 3)) instead of (suma2 1 2 3)) or use apply to call suma2 with the contents of the list as its arguments instead of the list itself.
Your function call in the second function (-> suma2) is wrong.
You expect your function to be called like this:
(suma2 1 2 3 4)
But the first recursive call is equivalent to this:
(suma2 '(2 3 4))
You pass a list, where individual elements are expected. See the documentation for APPLY.