Why getting unwanted NIL after right answer is returned in Lisp? - lisp

I am writing a lisp program called pellnumbers to return a list of pell numbers. However, I always get NIL right after a test result. I am new to Lisp and do not understand much about its errors. Could you please help me out? Thank you!
Below is my code
;define a function of how to compute a pell number
(defun P (n)
(cond
((= n 0) 0)
((= n 1) 1)
(t (+ (* 2 (P (- n 1))) (P (- n 2))))))
;define an iterative function to return a sequence of pell numbers
(defun pellnumbers (n)
(prog
(setq res '())
(loop for i from 0 to n
do (setq res (append res (list (P i))))
)
(print res)))
;test cases
(print (pellnumbers 0))
(print (pellnumbers 6))
(print (pellnumbers 9))
and here is the result I get
(0)
NIL
(0 1 2 5 12 29 70)
NIL
(0 1 2 5 12 29 70 169 408 985)
NIL

NIL is not an error. It's just a a piece of data, which is both a symbol and means the empty list.
a few hints for your code:
it's unclear why you use PROG but you need to check it's syntax
The syntax of PROG:
prog
({var | (var [init-form])}*)
declaration*
{tag | statement}*
Your code lacks a list of variables. The form (setq res '()) is wrong.
Why not just use LET instead.
you need to indent your code properly
Example indent:
(defun pellnumbers (n)
(prog
(setq res '())
(loop for i from 0 to n
do (setq res (append res (list (P i)))))
(print res)))
This makes it easier to spot syntax errors. Again: your usage of PROG is a) wrong and b) not needed.
your code prints twice
There is a print statement inside the function pellnumbers and your testcases also have a print statement.
That's why two values are being printed. The result of pellnumbers is always NIL, so always NIL is printed, for any testcase in your code.

Remember that the last form evaluated is the return value. print returns NIL, and being the last form in the prog, prog returns NIL, which becomes the return value for pellnumbers.
Whether you use prog, progn or let is a matter of taste.

Related

Common LIsp issue with Macros and variables

I have an assignment where I need to write a script using lisp. I am having issues with passing variables
Here is the code. Issues to follow:
(defmacro while (test &rest bodies)
`(do ()
((not ,test))
,# bodies)
)
(defmacro += (var inc)
`(print (eval var))
;(setf (eval var) (+ (eval var) inc))
)
(defmacro iterate (i begin end inc &rest others)
(setf i begin)
(while (<= i (eval end))
;(dolist (item others)
; (eval item)
;)
(print (list 'two i (eval end)))
(+= (eval end) 1)
(setf i (+ i inc))
)
)
(setf n 5)
(iterate i 1 n 1
(print (list 'one i))
(+= n 1)
)
The first issue lies in passing the statements to the iterate macro. When I try to run the commented out dolist, the print statement will throw an error when it comes to the variable i. For some reason I can not get it to print using the macro variable i which has a value, but it seems to want to default to the global variable i which has not been set. I get the error:
- EVAL: variable I has no value
The second issue is when I call the "+=" macro. The value of end in the iterate macro is 5 as passed to the macro by use of the variable N which it is set to 5, however, when I pass it to the "+=" macro using the line "(+= (eval end) 1)" I can not get it to pass the value. I tried removing the eval in the line "(+= (eval end) 1)" and when I try printing it with "(print (eval var))" in the "+=" macro, I get the error
- EVAL: variable END has no value
How would I solve these issues?
Your first macro is basically correct. It generates code.
(defmacro while (test &body body)
`(do ()
((not ,test))
,#body))
One can check it with an example. We expand the macro using example code. The function MACROEXPAND-1 expands the top-level macro exactly once. You need to pass code to the function MACROEXPAND-1:
CL-USER 1 > (macroexpand-1 '(while (< i 10)
(print i)
(incf i)))
(DO NIL ; NIL is the same as ()
((NOT (< I 10)))
(PRINT I)
(INCF I))
T
The generated code is a DO loop. Just like intended.
Thus we can use your macro:
CL-USER 2 > (let ((i 5))
(while (< i 10)
(print i)
(incf i)))
5
6
7
8
9
NIL
Your other macros should be like that
they should generate code
macro expansion of examples should show the right generated code
the generated code should work
Your macros should NOT
be using EVAL
try to compute results other than code

How to modify list inside a function

(defun list-parser (list count)
...);;this function reads items by count from list and do some process to them.
;;i.e.convert items read from code to char, or to other things and then return it.
;;Also, the items in list should be consumed, globally.
(defmethod foo ((obj objtype-2) data-list)
(setf (slot-1 obj) (read-list data-list 1))
obj)
(defmethod foo ((obj objtype-1) data-list)
(setf (slot-1 obj) (read-list data-list 1)
(print data-list)
(slot-2 obj) (read-list data-list 2)
(print data-list)
(slot-3 obj) (foo (make-instance 'objtype-2) data-list)
(print data-list)
(slot-4 obj) (read-list data-list 3))
obj)
How to let it work like this:(read-list just works like read-byte in some way:
1.return a value read(and parsed here)
2.change the stream position(here the list)).
(let ((obj)
(data))
(setf data '(1 2 3 4 5 6 7 8)
obj (foo (make-instance 'objtype-1) data))
(print data))
>>(2 3 4 5 6 7 8)
>>(4 5 6 7 8)
>>(5 6 7 8)
>>(8)
Or rather, how do you deal with this kind of task? Do you convert list to other type?
I am not quite sure what you are after, but here is a function which creates a 'list reader' object (just a function). A list reader will let you read chunks of a list, treating it a bit like a stream.
(defun make-list-reader (l)
;; Make a list reader which, when called, returns three values: a
;; chunk of list, the length of tha chunk (which may be less than
;; how much was asked for) and the remaining length. The chunk is
;; allowed to share with L
(let ((lt l)
(len (length l)))
(lambda (&optional (n 1))
(cond
((zerop len)
(values nil 0 0))
((< len n)
(values lt len 0))
(t
(let ((it (subseq lt 0 n)))
(setf lt (nthcdr n lt)
len (- len n))
(values it n len)))))))
(defun read-from-list-reader (r &optional (n 1))
;; Read from a list reader (see above for values)
(funcall r n))
And now:
(defvar *l* (make-list-reader '(1 2 3)))
*l*
> (read-from-list-reader *l* 1)
(1)
1
2
> (read-from-list-reader *l* 2)
(2 3)
2
0
> (read-from-list-reader *l* 10)
nil
0
0
What you can't really do is write a function (not actually a function of course since it modifies its argument) which works like this while modifying its argument list. So you can write a function which will do this:
> (let ((l (list 1 2)))
(values (read-from-list l)
l))
(1)
(2)
which works by modifying the car and cdr of the first cons of l as you'd expect. But this can't work when there is no more to read: l is a cons and nil isn't a cons, so you can't ever make l nil with a function.
But in any case such a function is just a mass of traps for the unwary and generally horrid: for instance your example would involve modifying a literal, which isn't legal.

How do I append a list recursively in common lisp?

(defun foo (in i out)
(if (>= i 0)
(progn
(append (list (intern (string (elt in i)))) out)
(print output)
(foo in (- i 1) out )
)
(out)
)
)
(print (foo "abcd" (- (length "abcd") 1) (list)))
I am trying to return this string as (a b c d). But it does return nil as output. What do I do wrong here? Thanks
I don’t know what this has to do with appending. I think your desired output is also weird and you shouldn’t do what you’re doing. The right object for a character is a character not a symbol. Nevertheless, a good way to get the list (a b c d) is as follows:
CL-USER> '(a b c d)
Interning symbols at runtime is weird so maybe you would like this:
(defconstant +alphabet+ #(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defun foo (seq)
(map 'list
(lambda (char)
(let ((index (- (char-code char) (char-code #\a))))
(if (< -1 index (length +alphabet+))
(svref +alphabet+ index)
(error "not in alphabet: ~c" char))))
seq))
You have just some minor mistakes. First, we need to get rid of output and (output); these bear no relation to the code. It seems you were working with a variable called output and then renamed it to out without fixing all the code. Moreover, (output) is a function call; it expects a function called output to exist.
Secondly, the result of append must be captured somehow; in the progn you're just discarding it. Here is a working version:
(defun foo (in i out)
(if (>= i 0)
(foo in (1- i) (cons (intern (string (elt in i))) out))
out))
Note also that instead of your (append (list X) Y), I'm using the more efficient and idiomatic (cons X Y). The result of this cons operation has to be passed to foo. The out argument is our accumulator that is threaded through the tail recursion; it holds how much of the list we have so far.
I.e. we can't have (progn <make-new-list> (foo ... <old-list>)); that just creates the new list and throws it away, and then just passes the old list to the recursive call. Since the old list initially comes as nil, we just keep passing along this nil and when the index hits zero, that's what pops out. We need (foo .... <make-new-list>), which is what I've done.
Tests:
[1]> (foo "" -1 nil)
NIL
[2]> (foo "a" 0 nil)
(|a|)
[3]> (foo "ab" 1 nil)
(|a| |b|)
[4]> (foo "abcd" 3 nil)
(|a| |b| |c| |d|)
[5]> (foo "abcd" 3 '(x y z))
(|a| |b| |c| |d| X Y Z)
Lastly, if you want the (|a| |b| |c| |d|) symbols to appear as (a b c d), you have to fiddle withreadtable-case.
Of course:
[6]> (foo "ABCD" 3 nil)
(A B C D)

Trying to return list of values at even positions in current list

The goal here is to pass a list to the function and have it return a list with the values at the even positions in that previous list.
eg. return-evens '(1 2 3) => (2) , return-evens '() => ()
I've finally created this function, however it is only working when I enter 0-3 values. And when I enter 0 or 1 values, instead of returning "()", it just returns "NIL".
How can I get this to work with more than 3 values, and how can I return it so that it prints it out as a list, with parentheses surrounding it?
(defun return-evens (lst)
(let ((return-list ()) (i 1))
(loop for x in lst
while (numberp x)
do (if (= (mod i 2) 0)
(setf return-list (append return-list x))
()
)
do (setq i (1+ i))
finally (return return-list))))
Some feedback to your code.
First big problem: it is not properly indented.
(defun return-evens (lst) ; in Lisp you can call it list instead of lst
; return is not a useful prefix.
; Every function returns something
(let ((return-list ()) (i 1)) ; LOOP can return lists and iterate.
; No need for this at all.
(loop for x in lst
while (numberp x) ; why this test? Are there non-numbers in the list?
do (if (= (mod i 2) 0) ; Lisp has a function EVENP
; but generally it is not necessary
(setf return-list (append return-list x))
; never append to the end. Never ever.
; Let LOOP collect a list, don't do it this way
()
)
do (setq i (1+ i)) ; iterating manually is not necessary
; that's what LOOP is for
finally (return return-list))))
; if you would let LOOP do the work, no RETURN necessary
A much simpler solution:
(defun elements-at-even-positions (list)
(loop for element in list
for even-position = nil then (not even-position)
when even-position collect element))

Lisp: Generating a list of 10 random integers

this is part of a my first homework in common lisp.
We have to define a variable representing any 10 random integers from 0 to 100:
I am not sure what is being asked here.
Should I write: (setf var1 '())
Then, we have to define a function that generates a list of 10 random integers and returns a list that contains those numbers.
Here is what I wrote, but I keep getting NIL as my output. Do you know what's wrong with the code:
(setf *random-state* (make-random-state t))
(setf var1 '())
(defun randlist (var1)
(dotimes (i 10)
(setf temp (random 101))
(cons 'temp var1 ) ) )
Write a function that returns a new list with 10 random integers:
(defun randlist ()
(let ((lst ()))
(dotimes (i 10)
(setf lst (cons (random 101) lst)))
lst))
And then you can assign its result to a variable:
(defvar var1 (randlist))
DEMO.
You don't need to initialize *random-state* like that. That's the default anyway. You'd need to initialize it if you have a different implementation of random number generator.
While (setf whatever nil) will probably work, this is not the way you declare variables. setf is a macro for assigning values to symbols. Normally you first create symbols and then assign to them. If you need a dynamic variable, your options are defparamter or defvar macros, e.g.:
(defparameter var1 nil)
(defvar var2 nil)
Your function randlist returns nil as this is what dotimes macro returns, and this is the last form executed in the function. You could've changed it to return var1, but the use of dynamic variables, especially in this way is not a good coding practice. It sounds from the task as if you were asked to simply write a function that returns a list of ten integers, no need to also assign that to a dynamic variable outside the function.
(defun randlist ()
(loop for i from 0 below 10 collect (random 101)))
Would be perhaps the simplest way to do it. But there are really lots and lots of other ways :)
Just for fun, here's an alternative, it's not particularly good, though. I hoped for it to be shorter, but it wasn't really :)
(defun random-list ()
(mapcar #'random (make-list 10 :initial-element 101)))
Lets do this with recursion:
(defun rnd-list()
(rnd-list-1 10 10))
(defun rnd-list-1 (limit count)
(cond ((<= count 0)
nil)
(t
(cons (random limit)
(rnd-list-1 limit (1- count))))))
Or you can do like this --
(defun rnd-list()
(let (lst)
(dotimes (n 100)
(push (random 101) lst))
(reverse lst)))
Empowering do, iterate over n and define lst as a void list; when n reaches 10 return lst. On every iteration push one random number to lst.
(do ((n 1 (incf n))
(lst ()))
((> n 10) lst)
(push (random 101) lst))
=> (31 35 59 19 84 54 62 44 69 54)