How do I use cons or other way to print a list of Pell numbers till the Nth number?
(defun pellse (k)
(if (or (zerop k) (= k 1))
k
(+ (* 2 (pellse (
Here is an approach to solving this problem which works by defining an infinite stream of Pell numbers. This is based on the ideas presented in SICP, and particularly section 3.5. Everyone should read this book.
First of all we need to define a construct which will let us talk about infinite data structures. We do this by delaying the evaluation of all but a finite part of them. So start with a macro called delay which delays the evaluation of a form, returning a 'promise' (which is a function of course), and a function called force which forces the system to make good on its promise:
(defmacro delay (form)
;; Delay FORM, which may evaluate to multiple values. This has
;; state so the delayed thing is only called once.
(let ((evaluatedp-n (make-symbol "EVALUATEDP"))
(values-n (make-symbol "VALUES")))
`(let ((,evaluatedp-n nil) ,values-n)
(lambda ()
(unless ,evaluatedp-n
(setf ,evaluatedp-n t
,values-n (multiple-value-list
(funcall (lambda () ,form)))))
(values-list ,values-n)))))
(defun force (promise)
;; force a promise (delayed thing)
(funcall promise))
(This implementation is slightly overcomplex for our purposes, but it's what I had to hand.).
Now we'll use delay to define streams which are potentially infinite chains of conses. There are operations on these corresponding to operations on conses but prefixed by stream-, and there is an object called null-stream which corresponds to () (and is in fact the same object in this implementation).
(defmacro stream-cons (car cdr)
;; a cons whose cdr is delayed
`(cons ,car (delay ,cdr)))
(defun stream-car (scons)
;; car of a delayed cons
(car scons))
(defun stream-cdr (scons)
;; cdr of a delayed cons, forced
(force (cdr scons)))
(defconstant null-stream
;; the empty delayed cons
nil)
(defun stream-null (stream)
;; is a delayed cons empty
(eq stream null-stream))
Now define a function pell-stream which returns a stream of Pell numbers. This function hand-crafts the first two elements of the stream, and then uses a generator to make the rest.
(defun pell-stream ()
;; A stream of Pell numbers
(labels ((pell (pn pn-1)
(let ((p (+ (* 2 pn) pn-1)))
(stream-cons p (pell p pn)))))
(stream-cons 0 (stream-cons 1 (pell 1 0)))))
And now we can simply repeatedly takes stream-cdr to compute Pell numbers.
(defun n-pell-numbers (n)
(loop repeat n
for scons = (pell-stream) then (stream-cdr scons)
collect (stream-car scons)))
And now
> (n-pell-numbers 20)
(0
1
2
5
12
29
70
169
408
985
2378
5741
13860
33461
80782
195025
470832
1136689
2744210
6625109)
Note that, in fact, pell-stream can be a global variable: it doesn't need to be a function:
(defparameter *pell-stream*
(labels ((pell (pn pn-1)
(let ((p (+ (* 2 pn) pn-1)))
(stream-cons p (pell p pn)))))
(stream-cons 0 (stream-cons 1 (pell 1 0)))))
(defun n-stream-elements (stream n)
(loop repeat n
for scons = stream then (stream-cdr scons)
collect (stream-car scons)))
If we define a little benchmarking program:
(defun bench-pell (n)
(progn (n-stream-elements *pell-stream* n) n))
Then it's interesting to see that this is clearly essentially a linear process (it slows down for later elements because the numbers get big and so operations on them take a long time), and that the stateful implementation of promises makes it much faster after the first iteration (at the cost of keeping quite a lot of bignums around):
> (time (bench-pell 100000))
Timing the evaluation of (bench-pell 100000)
User time = 2.020
System time = 0.803
Elapsed time = 2.822
Allocation = 1623803280 bytes
441714 Page faults
100000
> (time (bench-pell 100000))
Timing the evaluation of (bench-pell 100000)
User time = 0.007
System time = 0.000
Elapsed time = 0.006
Allocation = 1708248 bytes
0 Page faults
100000