Even maximums in Lisp [duplicate] - recursion

This question already has answers here:
Common lisp error: "should be lambda expression"
(4 answers)
Closed 5 years ago.
I'm trying to make a function that changes infix input to prefix eg : (x + 1) as input outputted as (+ x 1).
So here is my code for the moment :
(setq x '(Y + 1))
(if (listp x ) (list (second x) (first x) (first (last x))) x)
so it returns (+ Y 1) if I input a list and the user input if it's not a list.
However, the problem is that I can't get this code working in a function :
(defun prefixToInfix (x)(
(if (listp x ) (list (second x) (first x) (first (last x))) x)
)
)
the function is indeed created but when I call it
(prefixtoinfix '(Y + 1))
I get an error
Error: Illegal function object: (IF (LISTP X) (LIST # # #) X).
[condition type: TYPE-ERROR]
I don't know why my if statement works in the main program but doesn't when I run it from my function.

What you are missing is that in Lisp parentheses are meaningful.
In C/Java/Python &c, the following expressions are the same:
a+b
(a+b)
(a)+(b)
(((a)+(b)))
(((((a)+(b)))))
In Lisp, the following expressions are very different:
a --- a symbol
(a) --- a list with a single element, which is the symbol a
(1 (2)) --- a list of two elements:
number 1
list of of length 1, containing number 2
In your case, function (note indentation and paren placement!)
(defun prefixToInfix (x)
((if (listp x) (list (second x) (first x) (first (last x))) x)))
has extra parens around if (and this causes the whole if form to be interpreted as a function, with disastrous results), and should be (note line breaks and indentation - lispers do not count parens, they look at indentation to understand the code, see http://lisp-lang.org/style-guide/)
(defun prefix-to-infix (x)
(if (listp x)
(list (second x)
(first x)
(first (last x)))
x))
PS. See also recommendations in want to learn common lisp.

Related

Using symbol parameters in a function without parentheses and quote in Common Lisp

(defun all-longer-than-1-char? (&rest elements)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
elements))
(all-longer-than-1-char? "OK" "NO" 1)
I'd like this function to work on symbol parameters (i.e. without having to double quote or to enter numbers) but it doesn't work. To make it work with symbol parameters:
(defun all-longer-than-1-char? (lst)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
lst))
(all-longer-than-1-char? '(OK NO 1))
NIL
But this time I have to enclose the parameters inside parentheses and quote it. I'd like to make it work both with symbol parameters and without having to put parameters inside parentheses and quote them, like:
(all-longer-than-1-char? OK NO 1)
How to do it?
You can use &rest to create what would once have been called a 'nospread' function (or an 'lexpr' depending on your religion), which is very often less useful other than as a user-interface since if you have a list of things you then have to use apply.
Common Lisp doesn't have functions which don't evaluate their arguments, which was once what was known as a 'nlambda' (or an 'fexpr' if you belong to the wrong cult), so you need to quote forms which would otherwise mean something to the evaluator.
You can get the same result as an nlambda with a macro. But you almost certainly don't want to do that as it smells like a bad use of a macro.
Given
(defun all-longer-than-1-char-p (list)
(every (lambda (x)
(> (length
(etypecase x
(string x)
(integer (write-to-string x))
(symbol (symbol-name x))))
1))
list))
Then the nospread one might be
(defun all-longer-than-1-char-p/nospread (&rest list)
(all-longer-than-1-char list))
And the nlambda one might be
(defmacro all-longer-than-1-char-p/quoted/nospread (&rest things)
`(all-longer-than-1-char ',things))
So now
> (all-longer-than-1-char-p '(xx yy 12 "foo"))
t
> (all-longer-than-1-char-p/nospread 'xx 'yy 12 "foo")
t
> (all-longer-than-1-char-p/quoted/nospread xx yy 12 "foo")
t
(All assuming *print-base* is less than 13).
But
> (let ((x "xx"))
(all-longer-than-1-char-p/quoted/nospread x))
nil
So, not very semantically useful, and kind of a poster child for how not to use macros.

Why are this list's contents retained between function calls? [duplicate]

Could someone explain to me what's going on in this very simple code snippet?
(defun test-a ()
(let ((x '(nil)))
(setcar x (cons 1 (car x)))
x))
Upon a calling (test-a) for the first time, I get the expected result: ((1)).
But to my surprise, calling it once more, I get ((1 1)), ((1 1 1)) and so on.
Why is this happening? Am I wrong to expect (test-a) to always return ((1))?
Also note that after re-evaluating the definition of test-a, the return result resets.
Also consider that this function works as I expect:
(defun test-b ()
(let ((x '(nil)))
(setq x (cons (cons 1 (car x))
(cdr x)))))
(test-b) always returns ((1)).
Why aren't test-a and test-b equivalent?
The Bad
test-a is self-modifying code. This is extremely dangerous. While the variable x disappears at the end of the let form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be passed around (just like a number or a list), and, sometimes, modified. This is exactly what you are doing here: the initial value for x is a part of the function object and you are modifying it.
Let us actually see what is happening:
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote (nil)))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1 1))))) (setcar x (cons 1 (car x))) x))
The Good
test-b returns a fresh cons cell and thus is safe. The initial value of x is never modified. The difference between (setcar x ...) and (setq x ...) is that the former modifies the object already stored in the variable x while the latter stores a new object in x. The difference is similar to x.setField(42) vs. x = new MyObject(42) in C++.
The Bottom Line
In general, it is best to treat quoted data like '(1) as constants - do not modify them:
quote returns the argument, without evaluating it. (quote x) yields x.
Warning: quote does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader (see info node
Printed Representation). This means that (a . b) is not
identical to (cons 'a 'b): the former does not cons. Quoting should
be reserved for constants that will never be modified by side-effects,
unless you like self-modifying code. See the common pitfall in info
node Rearrangement for an example of unexpected results when
a quoted object is modified.
If you need to modify a list, create it with list or cons or copy-list instead of quote.
See more examples.
PS1. This has been duplicated on Emacs.
PS2. See also Why does this function return a different value every time? for an identical Common Lisp issue.
PS3. See also Issue CONSTANT-MODIFICATION.
I found the culprit is indeed 'quote. Here's its doc-string:
Return the argument, without evaluating it.
...
Warning: `quote' does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader
...
Quoting should be reserved for constants that will
never be modified by side-effects, unless you like self-modifying code.
I also rewrote for convenience
(setq test-a
(lambda () ((lambda (x) (setcar x (cons 1 (car x))) x) (quote (nil)))))
and then used
(funcall test-a)
to see how 'test-a was changing.
It looks like the '(nil) in your (let) is only evaluated once. When you (setcar), each call is modifying the same list in-place. You can make (test-a) work if you replace the '(nil) with (list (list)), although I presume there's a more elegant way to do it.
(test-b) constructs a totally new list from cons cells each time, which is why it works differently.

Average using &rest in lisp

So i was asked to do a function i LISP that calculates the average of any given numbers. The way i was asked to do this was by using the &rest parameter. so i came up with this :
(defun average (a &rest b)
(cond ((null a) nil)
((null b) a)
(t (+ (car b) (average a (cdr b))))))
Now i know this is incorrect because the (cdr b) returns a list with a list inside so when i do (car b) it never returns an atom and so it never adds (+)
And that is my first question:
How can i call the CDR of a &rest parameter and get only one list instead of a list inside a list ?
Now there is other thing :
When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there.
My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
EDIT: I know the function only does the + operation, i know i have to divide by the length of the b list + 1, but since i got this error i'd like to solve it first.
(defun average (a &rest b)
; ...
)
When you call this with (average 1 2 3 4) then inside the function the symbol a will be bound to 1 and the symbol b to the proper list (2 3 4).
So, inside average, (car b) will give you the first of the rest parameters, and (cdr b) will give you the rest of the rest parameters.
But when you then recursively call (average a (cdr b)), then you call it with only two arguments, no matter how many parameters where given to the function in the first place. In our example, it's the same as (average 1 '(3 4)).
More importantly, the second argument is now a list. Thus, in the second call to average, the symbols will be bound as follows:
a = 1
b = ((3 4))
b is a list with only a single element: Another list. This is why you'll get an error when passing (car b) as argument to +.
Now there is other thing : When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there. My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
(null b) will only be truthy when b is the empty list. But when you call (average a '()), then b will be bound to (()), that is a list containing the empty list.
Solving the issue that you only pass exactly two arguments on the following calls can be done with apply: It takes the function as well as a list of parameters to call it with: (appply #'average (cons a (cdr b)))
Now tackling your original goal of writing an average function: Computing the average consists of two tasks:
Compute the sum of all elements.
Divide that with the number of all elements.
You could write your own function to recursively add all elements to solve the first part (do it!), but there's already such a function:
(+ 1 2) ; Sum of two elements
(+ 1 2 3) ; Sum of three elements
(apply #'+ '(1 2 3)) ; same as above
(apply #'+ some-list) ; Summing up all elements from some-list
Thus your average is simply
(defun average (&rest parameters)
(if parameters ; don't divide by 0 on empty list
(/ (apply #'+ parameters) (length parameters))
0))
As a final note: You shouldn't use car and cdr when working with lists. Better use the more descriptive names first and rest.
If performance is critical to you, it's probably best to fold the parameters (using reduce which might be optimized):
(defun average (&rest parameters)
(if parameters
(let ((accum
(reduce #'(lambda (state value)
(list (+ (first state) value) ;; using setf is probably even better, performance wise.
(1+ (second state))))
parameters
:initial-value (list 0 0))))
(/ (first accum) (second accum)))
0))
(Live demo)
#' is a reader macro, specifically one of the standard dispatching macro characters, and as such an abbreviation for (function ...)
Just define average*, which calls the usual average function.
(defun average* (&rest numbers)
(average numbers))
I think that Rainer Joswig's answer is pretty good advice: it's easier to first define a version that takes a simple list argument, and then define the &rest version in terms of it. This is a nice opportunity to mention spreadable arglists, though. They're a nice technique that can make your library code more convenient to use.
In most common form, the Common Lisp function apply takes a function designator and a list of arguments. You can do, for instance,
(apply 'cons '(1 2))
;;=> (1 . 2)
If you check the docs, though, apply actually accepts a spreadable arglist designator as an &rest argument. That's a list whose last element must be a list, and that represents a list of all the elements of the list except the last followed by all the elements in that final list. E.g.,
(apply 'cons 1 '(2))
;;=> (1 . 2)
because the spreadable arglist is (1 (2)), so the actual arguments (1 2). It's easy to write a utility to unspread a spreadable arglist designator:
(defun unspread-arglist (spread-arglist)
(reduce 'cons spread-arglist :from-end t))
(unspread-arglist '(1 2 3 (4 5 6)))
;;=> (1 2 3 4 5 6)
(unspread-arglist '((1 2 3)))
;;=> (1 2 3)
Now you can write an average* function that takes one of those (which, among other things, gets you the behavior, just like with apply, that you can pass a plain list):
(defun %average (args)
"Returns the average of a list of numbers."
(do ((sum 0 (+ sum (pop args)))
(length 0 (1+ length)))
((endp args) (/ sum length))))
(defun average* (&rest spreadable-arglist)
(%average (unspread-arglist spreadable-arglist)))
(float (average* 1 2 '(5 5)))
;;=> 3.25
(float (average* '(1 2 5)))
;;=> 2.66..
Now you can write average as a function that takes a &rest argument and just passes it to average*:
(defun average (&rest args)
(average* args))
(float (average 1 2 5 5))
;;=> 3.5
(float (average 1 2 5))
;;=> 2.66..

What's wrong with my Lisp code?

I have some lisp code that I have to write multiple different ways. I've tried two different ways and I'm unsure of why they don't work. The function has to take a list and return only integers in that list. The first one has to take a map function and the second one has to use loop. This is in Clisp.
Here is my code.
(defun posint1 (l)
(mapcan #'(lambda (x)
(and (integerp x)
(list l)))))
and
(defun posint1 (l)
(loop for x in (list l)
when (integerp x)
collect x)
(format t "~A " x))))
mapcan requires at least one list argument and you have supplied none in your first function (I can't use names since you call both the same)
The second function tried to format a variable, x, that does not exist in that scope. In loop x are the one element in (list l) which probably should just be l since making a one number list doesn't really need iteration. Perhaps you wanted something like:
(defun print-integers (list)
(loop :for x :in list
:when (integerp x)
:collect x :into result
:finally (format t "~A " result)))
;; or using the result as argument
(defun print-integers (list)
(format t
"~A "
(loop :for x :in list
:when (integerp x)
:collect x)))
(print-integers '(-1 0.5 1/3 +inf.0 9)) ; ==> NIL (prints (-1 9)
Also notice that integerp works for whole numbers, also negative ones. The name hinted that you might want to use (and (integerp x) (>= x 0)) instead.

Trouble returning recursively-built lists to calling functions in Lisp

I am new to Lisp and have an issue regarding recursion and function returns. In the interests of trying to better understand and solve my problem, I provide the following scenario. I apologize if it is verbose. If this aggravates others, I'm happy to trim it down. To skip right to the business, please read from the horizontal line onward.
Imagine a waitress at a bar. Instead of taking drink orders, she forces her patrons to identify themselves as drinkers of beer, rum, whiskey, or some combination of these. Then she grabs a tray full of either beer, rum or whiskey and does a lap around the bar, leaving exactly one drink with any customer who has identified themself as a drinker of that particular beverage. When she's finished each round, she always sits down and has a Long Island Ice Tea. Afterward, she proceeds to grab another tray of exclusively one type of drink and goes out for delivery again. No customer can ever refuse a drink, and no one can change their drink preferences.
Now, Mindy (the waitress) needs a novel way of keeping track of how many drinks of each type she is delivering to each patron. Mindy isn't very good at math and by the end of the night all of those Long Island Ice Teas are really adding up.
So when she asked for a simple solution for tracking her drink dispensing, I naturally suggested creating a simple little Lisp program. Here's how it is to work: When she has finished delivering a round of tasty beverages, Mindy simply walks up to her Altair 8800 and types the following:
(update-orders <order-list> <drink>)
where is the list of all customers and their orders, and is the drink she just served in her most recent outing.
It should properly go through the lists of customers and their drink counts, updating the proper drinks by one and leaving the others alone. To interface with the computer system in place, a newly-updated orders-list needs to be returned from the function when it is complete.
Just today I came across the following bug: after properly calling the function, the value returned is not what I want. The list only includes the very last drink count list of the very first customer in the list, every time. Recursive programming is the real culprit here, as opposed to Lisp, and I have tried altering the code to fix this, but to no avail. I need a full list returned from the function.
As you may have guessed, this story is not true. The real problem I am trying to solve is related to calculus, and is a well-known topic for those getting their feet wet with Lisp. However, my problem is not with my assignment, but rather with wrapping my mind around the recursive calls and returning full lists of values to calling functions, so that I may build a complete list of all terms to return when finished. After I am able to solve this sub-problem, I am just a stones throw away from applying it to my actual assignment and solving it.
Running the following function call:
(update-orders (quote ( (bill (4 beer) (5 whiskey)) (jim (1 beer)) (kenny (1 whiskey) (4 rum)) (abdul (1 beer) (3 whiskey) (2 rum) ))) (quote beer))
gets me the following returned:
((5 WHISKEY))
I would, instead, like a list in the same format as the one supplied to the function above.
Please see the code below. It has been modified to include debugging output to the screen for convenience. Function drink-list is likely where my trouble lies.
(defun update-orders (x d)
(print 'orders)
(prin1 x)
(order (car x) d)
)
(defun order (x d)
(print 'order)
(prin1 x)
(drink-list (cdr x) d)
)
(defun drink-list (x d)
(print 'drink-list)
(prin1 x)
;(append
;(cons
;(list
(drink-count (car x) d)
(cond
((cdr x) (drink-list (cdr x) d))
(t x)
)
;)
)
(defun drink-count (x d)
(print 'drink-count)
(prin1 x)
(list
(cond
((eq (car (cdr x)) d)
(modify-count (car x) 1))
(t x)
)
)
)
(defun modify-count (x d)
(print 'modify-count)
(prin1 x)
(print 'new-modify-count)
(prin1 (+ (parse-integer (subseq (write-to-string x) 0)) 1))
(list
(+ (parse-integer (subseq (write-to-string x) 0)) 1)
)
)
EDIT:
I have incorporated ooga's suggestions into my code. The new order and update-order functions are shown below:
(defun update-orders (x d)
(cond
((null x) ())
(t (cons (order (car x) d) (update-orders (cdr x) d)))
)
)
(defun order (x d)
;(print 'order)
;(prin1 x)
(drink-list (cdr x) d)
)
I now get the following list returned, running the same function call as above:
(((5 WHISKEY)) ((1 BEER)) ((4 RUM)) ((2 RUM)))
which is a list of embedded lists (2 deep, I believe) that include all of the last drink item and drink count of each patron in the list (Bill's final list entry is 5 whiskey, Jim final entry is 1 beer, etc). Their first n-1 drinks are not added to the returned list of their drinks.
Have I misread your suggestion? I have a feeling I am a half step away here.
In update-orders you only pass the car of x to order. The rest of x is completely ignored. Then you only pass the cdr of that is on to drink-list.
As an example of how your code should be structured, here's a program that adds 1 to each member of the given list.
Example call: (increment-list '(1 2 3))
(defun increment-list (x)
(cond
((null x) ())
(t (cons (increment (car x)) (increment-list (cdr x))))
)
)
(defun increment (x)
(+ x 1)
)
Change increment-list to update-orders and increment to orders (and add the second input, etc.) and that, I think, should be your program structure.
Also, you should try to build it from the bottom up. Try writing a function that will add one to the number if the given drink in a (number drink) list matches. I.e., given this:
(add-one-if '(4 beer) 'beer)
It should return this
(5 BEER)
And given this
(add-one-if '(3 whiskey) 'beer)
It should return this
(3 WHISKEY)
As suggest above, here is the full code I have implemented to solve my problem, incorporating the suggested structure provided by ooga.
;;;; WAITING-TABLES
(defun update-orders (x d)
(cond
((null x) ())
(t (cons (order (car x) d) (update-orders (cdr x) d)))
)
)
(defun order (x d)
(cons (car x) (drink-list (cdr x) d))
)
(defun drink-list (x d)
(cond
((null x) ())
(t (cons (drink-count (car x) d) (drink-list (cdr x) d)))
)
)
(defun drink-count (x d)
(cond
((eq (car (cdr x)) d)
(cons (modify-count (car x) 1) (drink-count (cdr x) d)))
(t x)
)
)
(defun modify-count (x d)
(+ (parse-integer (subseq (write-to-string x) 0)) 1)
)

Resources