Does anyone knows why I'm getting this error?
EVAL/APPLY: Too few arguments (1 instead of at least 2) given to SUMTAIL .
(defun sum (n)
(sumTail 0 n)
)
(defun sumTail(r n)
(if (null n)
r
(sumTail (+ (first n) r) (rest n) )
)
)
(sumtail '(59 21 6 5 30 98 17 22 1 0))
First, let's rewrite the functions so we can read them better:
(defun sumTail (r n)
(if (null n)
r
(sumTail (+ (first n) r) (rest n))))
(defun sum (n)
(sumTail 0 n))
Now, it is easy to see the reason of the error: you call sumtail with a single argument:
(sumTail '(59 21 6 5 30 98 17 22 1 0))
while it has been defined as requiring two arguments, to be bound to the parameters r and n.
But we can see that sum requires only an argument, and it calls correctly sumtail with 0 and the list.
So, when you have just an argument, you should call sum:
CL-USER> (sum '(59 21 6 5 30 98 17 22 1 0))
259
Note that sumTail is equivalent to sumtail, since in Common Lisp, unless you modify the reader, both symbols are read as SUMTAIL.
Finally, you can use just a single function if you exchange the arguments:
(defun sumtail (n &optional (r 0))
(if (null n)
r
(sumTail (rest n) (+ (first n) r))))
CL-USER> (sumtail '(59 21 6 5 30 98 17 22 1 0))
259
This is because we have defined the second argument as optional, with an initial value of 0 when not provided.
Related
I am trying to write a function that creates a list of the fibonacci sequence but stops when a certain value is found in the list, then returns that list (I hope that makes sense).
So for example if I give it fib-list(55), the function should return:
(1 1 2 3 5 8 13 21 34 55)
So it's not the 55th fibonacci number I want, its the list UP TO the value 55.
The code I have for returning the list so far looks like this:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((equal? n (car fs)) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
(display (fib-list 55))
My main problem is finding if an element is in the list, because at the moment I just get an error on the line where I am trying to write the ((equal? statement.
The error says:
mcar: contract violation
expected: mpair?
given: '()
I am still very VERY new to Scheme, so my understanding of the language as a whole isn't great. So please be gentle when telling me why my code sucks/doesn't make sense.
(list) creates an empty list, and on the first iteration you get to (car fs), which tries to apply car to an empty list, and that's an error.
Your code seems a bit confused about the nature of n.
Your description says that it's the largest number you want, but you're recursing like you want the n:th Fibonacci number - terminating on (zero? n) and recursing on (- n 1).
When you're recursing you're still looking for numbers up to the same limit.
Thus, you should not decrement your limit and terminate on zero, you should leave the limit alone and terminate when you reach larger numbers.
Here's how I would write it:
The initial list is (1 1)
At each step:
Compute the next fibonacci number
If this is greater than the limit, reverse the accumulator list and return it
Otherwise, cons it to the accumulator and recurse with the "new" last two fibonacci number.
In code:
(define (fib-list n)
(let loop ((f2 1) (f1 1) (fs '(1 1)))
(let ((next (+ f1 f2)))
(if (> next n)
(reverse fs)
(loop f1 next (cons next fs))))))
Here's another way you can do it using continuation-passing style. By adding a continuation parameter to our loop, we effectively create our own return mechanism. One unique property of this implementation is the output list is built in forward order and does not need to be reversed when n reaches zero.
(define (fib-list n)
(let loop ((n n) (a 0) (b 1) (return identity))
(if (zero? n)
(return empty)
(loop (sub1 n)
b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 10)
;; '(0 1 1 2 3 5 8 13 21 34)
Reading your question a little closer, in fib-list(N) you need N to be the stopping condition for your loop, not the Nth term in the list. This is actually easier to implement as there's no need to count the number of terms generated.
(define (fib-list max)
(let loop ((a 0) (b 1) (return identity))
(if (> a max)
(return empty)
(loop b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 55)
;; '(0 1 1 2 3 5 8 13 21 34 55)
(fib-list 1000)
;; '(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987)
What's going wrong with the car function?
The car function takes the first element of a list, but if the list is empty it doesn't have a first element. The fs list starts out as empty. When you try to take the first element of an empty list you get this error message:
> (car (list))
mcar: contract violation
expected: mpair?
given: ()
If the list isn't empty, then it has a first element, and it's fine:
> (car (list 4 5 6))
4
Following what you meant in the comment
However, your comment "Check if n is in list" leads me to believe that (equal? n (car fs)) is not what you want anyway. The function for determining whether an element is in a list is called member.
#!r6rs
(import (rnrs base)
(rnrs lists))
> (if (member 4 (list 1 2 4 8))
"it's in the list"
"go fish")
"it's in the list"
> (if (member 5 (list 1 2 4 8))
"it's in the list"
"go fish")
"go fish"
So with that (equal? n (car fs)) test replaced with (member n fs), your code looks like:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((member n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(10946 6765 4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1)
This is not the answer you wanted though; you wanted (1 1 2 3 5 8 13 21 34 55).
Why is the list going past 55?
One of the problems is that the n is shadowed, in the same way that in this expression:
> (let ([n 5])
(let ([n 10])
n))
10
The n in the body refers to 10 instead of 5.
The result is going past 55 because inside the loop n is shadowed and has become a different number. I'm guessing in your comment about "check if n is in list", you meant "check if the original n is in list". To do that you have to rename one of the ns:
> (let ([orig-n 5])
(let ([n 10])
orig-n))
5
In the context of your code:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return list.
((member orig-n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(55 34 21 13 8 5 3 2 1 1)
Reversing
This is closer, but it's reversed. You have two base cases, the (zero? n) case and the (member orig-n fs) case. In one of those it's reversed and in one of them it's not. Changing them both to call reverse fixes it:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
Small numbers
This is correct on large Fibonacci numbers like 55, but it still does something weird on small numbers:
> (fib-list 2)
(1 1)
> (fib-list 3)
(1 1 2)
If you only want it to stop when it gets to orig-n, then maybe the decreasing n argument is not needed, and is actually making it stop too early. Removing it (and removing the zero check for it) makes the member check the only stopping case.
This is dangerous, because it could go into an infinite loop if you give it a non-Fibonacci number as input. However, it fixes the small-number examples:
; Create a list of the fibonacci sequence up to n.
; The `orig-n` MUST be a fibonacci number to begin with,
; otherwise this loops forever.
(define (fib-list orig-n)
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 2)
(1 1 2)
> (fib-list 3)
(1 1 2 3)
And finally, consider what happens vs. what should happen if you give it a number like 56.
> (fib-list 56)
;infinite loop
This is a design decision that you have not specified in your question (yet), but there are ways of solving it either way.
Update: orig-n or greater
I should have specified that I need to check if there is a number that is greater than OR equal to orig-n. Can I still use the member function to check for this or will I need to use something different?
You will have to use something different. Just above member in the documentation is the memp function (you could also use exists in this case). The mem is short for member, and the p is short for "predicate". It determines whether any member of the list matches a certain predicate.
> (if (memp positive? (list -4 -2 -3 5 -1))
"one of them is positive"
"go fish")
"one of them is positive"
> (if (memp positive? (list -4 -2 -3 -5 -1))
"one of them is positive"
"go fish")
"go fish"
> (define (five-or-greater? n)
(>= n 5))
> (if (memp five-or-greater? (list -4 -2 -3 6 -1))
"one of them is equal to 5 or greater"
"go fish")
"one of them is equal to 5 or greater"
> (if (memp five-or-greater? (list -4 -2 -3 4 -1))
"one of them is equal to 5 or greater"
"go fish")
"go fish"
To use it for "orig-n or greater", you would have to define a function like:
(define (orig-n-or-greater? n)
(>= n orig-n))
As a local function inside your main function, so that it can refer to orig-n. Then you can use it like (memp orig-n-or-greater? fs).
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
(define (orig-n-or-greater? n)
(>= n orig-n))
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n or greater is in list. If so, return reversed list.
((memp orig-n-or-greater? fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 3)
(1 1 2 3)
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 56)
(1 1 2 3 5 8 13 21 34 55 89)
I would like to write a function prime-seq to show a list between two numbers, using from and to.
Here is my code, I think it is if the numbers from the list are true then display them. But I have no idea how to write it, I am very new for this language.
(defn is-prime? [n]
(empty?
(filter #(= 0 (mod n %)) (range 2 n))))
(defn prime-seq [from to]
(drop from (take to is-prime?)))
the result should be:
(prime-seq 1 5)
=> (2 3 5)
You're very close:
(defn is-prime? [n]
(empty? (filter #(= 0 (mod n %)) (range 2 n))))
(defn prime-seq [from to]
(filter is-prime? (range from (inc to))))
(prime-seq 1 29)
=> (1 2 3 5 7 11 13 17 19 23 29)
This is using range generate a sequence of all numbers between from and to (inclusive), then filtering that list using your is-prime? predicate.
As for your is-prime? predicate, there are many approaches to determining primeness. As you comment (mod 1 1) => 0, so your predicate returns true however 1 isn't a prime number. You can simply add a special case for this in your predicate so that any number less than 2 returns false:
(defn is-prime? [n]
(if (< 1 n)
(empty? (filter #(= 0 (mod n %)) (range 2 n)))
false))
Or slightly more terse using and:
(defn is-prime? [n]
(and (< 1 n)
(not (some #(= 0 (mod n %)) (range 2 n)))))
In case people come here for a reasonably fast algorithm for finding prime numbers implemented in Clojure, here's an implementation of the Sieve of Eratosthenes in Clojure (using JVM arrays):
(defn find-primes
"Finds all prime numbers less than n, returns them sorted in a vector"
[n]
(if (< n 2)
[]
(let [^booleans sieve (boolean-array n false)
s (-> n Math/sqrt Math/floor int)]
(loop [p 2]
(if (> p s)
(into []
(remove #(aget sieve %))
(range 2 n))
(do
(when-not (aget sieve p)
(loop [i (* 2 p)]
(when (< i n)
(aset sieve i true)
(recur (+ i p)))))
(recur (inc p))))))))
Example:
(find-primes 100)
=> [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
And some benchmarking:
(require '[criterium.core :as bench])
(bench/bench
(find-primes 100000))
;Evaluation count : 17940 in 60 samples of 299 calls.
; Execution time mean : 3.370834 ms
; Execution time std-deviation : 217.730604 µs
; Execution time lower quantile : 3.040426 ms ( 2.5%)
; Execution time upper quantile : 3.792958 ms (97.5%)
; Overhead used : 1.755126 ns
As a test for one of my classes, our teacher asked us to test a recursive and non-recursive approach to the famous Euclidean Algorithm:
Iterative
(defun gcdi (a b)
(let ((x a) (y b) r)
(while (not (zerop y))
(setq r (mod x y) x y y r))
x))
Recursive
(defun gcdr (a b)
(if (zerop b)
a
(gcdr b (mod a b))))
And then I ran a test:
(defun test-iterative ()
(setq start (float-time))
(loop for x from 1 to 100000
do (gcdi 14472334024676221 8944394323791464)) ; Fibonacci Numbers close to 2^64 >:)
(- (float-time) start))
(defun test-recursive ()
(setq start (float-time))
(loop for x from 1 to 100000
do (gcdr 14472334024676221 8944394323791464)) ; Fibonacci Numbers close to 2^64 >:)
(- (float-time) start))
And then I ran the timers:
(test-recursive)
: 1.359128475189209
(test-iterative)
: 1.7059495449066162
So my question is this, why did the recursive test perform faster than the iterative test? Isn't iterative almost always better than recursion? Is elisp an exception to this?
The theoretical answer is that the recursive version is actually tail
recursive and thus should compile to iteration.
However, disassembling
the functions reveals the truth:
byte code for gcdi:
args: (a b)
0 varref a
1 varref b
2 constant nil
3 varbind r
4 varbind y
5 varbind x
6 varref y
7:1 constant 0
8 eqlsign
9 goto-if-not-nil 2
12 constant mod
13 varref x
14 varref y
15 call 2
16 varset r
17 varref y
18 varset x
19 varref r
20 dup
21 varset y
22 goto 1
25:2 varref x
26 unbind 3
27 return
vs
byte code for gcdr:
args: (a b)
0 varref b
1 constant 0
2 eqlsign
3 goto-if-nil 1
6 varref a
7 return
8:1 constant gcdr
9 varref b
10 constant mod
11 varref a
12 varref b
13 call 2
14 call 2
15 return
You can see that the gcdr has almost half as many instructions, but contains two call instructions, which means that ELisp does not, apparently, convert the tail recursive call to iteration.
However, function calls in ELisp are relatively cheap and
thus the recursive version executes faster.
PS. While the question makes sense, and the answer is actually generally applicable (e.g., the same approach is valid for Python and CLISP, inter alia), one should be aware that choosing the right algorithm (e.g., linearithmic merge-sort instead of quadratic bubble-sort) is much more important than "micro-optimizations" of the implementation.
Hmm... indeed that's weird, since Emacs's implementation of function calls (and hence recursion) is not very efficient.
I just evaluated the code below:
(defun sm-gcdi (a b)
(let ((x a) (y b) r)
(while (not (zerop y))
(setq r (mod x y) x y y r))
x))
(defun sm-gcdr (a b)
(if (zerop b)
a
(sm-gcdr b (mod a b))))
(defun sm-test-iterative ()
(let ((start (float-time)))
(dotimes (_ 100000)
(sm-gcdi 14472334024676221 8944394323791464))
(- (float-time) start)))
(defun sm-test-recursive ()
(let ((start (float-time)))
(dotimes (_ 100000)
(sm-gcdr 14472334024676221 8944394323791464))
(- (float-time) start)))
and then tried M-: (sm-test-recursive) and M-: (sm-test-iterative) and sure enough the iterative version is faster for me. I then did M-: (byte-compile 'sm-gcdi) and M-: (byte-compile 'sm-gcdr) and tried again, and the speed difference was even larger.
So your measurements come as a surprise to me: they don't match my expectations, and don't match my tests either.
I started programming with lisp yesterday so please excuse if I am making some really newbie mistake. I am trying to create a function which calculates the bell numbers using the bell triangle and my recursive triangle function is not working properly. I am also sure if I got my recursive triangle function working that my recursive bell function is somehow also broken.
When I test my triangle function I get the output:
(defun bell(l n)
(if(< n 1)(list 1))
(if (= n 1)(last l))
(bell (triangle (reverse l) (last l) (list-length l)) (- n 1))
)
(defun triangle(pL nL i)
(if(<= i 0)
(write "equals zero!")
(reverse nL)
)
(triangle pL (append (list (+ (nth i pL) (nth i nL))) nL) (- i 1))
)
(write (triangle '(1) '(1) 0))
=>
"equals zero!""equals zero!"
*** - NTH: -1 is not a non-negative integer
For some reason, it is printing my debug code twice even though the function should be meeting my base case on the first call.
For some reason, it is printing my debug code twice even though the function should be meeting my base case on the first call.
It is printed twice because if is not doing what you think it does. The first if test is true, therefore equals zero! is printed. After that, a recursive call to triangle function is invoked. The test is again true (-1 <= 0), so equals zero! is again printed. Finally, you get an error because nthcdr function is called with -1. I strongly recommend you a good lisp debugger. The one from Lispworks is pretty good.
I honestly don't get the logic of what you were trying to achieve with your code. so I wrote mine:
(defun generate-level (l &optional (result))
"given a list l that represents a triangle level, it generates the next level"
(if (null l) result
(if (null result)
(generate-level l (list (car (last l))))
(generate-level (cdr l) (append result
(list (+ (car l)
(car (last result)))))))))
(defun bell (levels &optional (l))
"generate a bell triangle with the number of labels given by the first parameter"
(unless (zerop levels)
(let ((to-print (if (null l) (list 1) (generate-level l))))
(print to-print)
(bell (1- levels) to-print))))
Things to understand the implementation:
&optional (parameter): this parameter is optional and nil by default.
append concatenates two lists. I'm using it to insert in the back of the list.
let ((to-print x)) creates a new variable binding (local variable) called to-print and initialized to x.
I almost forgot to mention how if works in common lisp:
(if (= x 1) y z) means if x is equal to 1 then return y, otherwise z.
Now if you call the function to create a Bell triangle of 7 levels:
CL-USER 9 > (bell 7)
(1)
(1 2)
(2 3 5)
(5 7 10 15)
(15 20 27 37 52)
(52 67 87 114 151 203)
(203 255 322 409 523 674 877)
NIL
It would be nicer to print it with the appropiate padding, like this:
1
1 2
2 3 5
5 7 10 15
15 20 27 37 52
52 67 87 114 151 203
203 255 322 409 523 674 877
but I left that as an exercise to the reader.
Your ifs don't have any effect. They're evaluated, and produce results, but then you discard them. Just like
(defun abc ()
'a
'b
'c)
would evaluate 'a and 'b to produce the symbols a and b, and then would evaluate 'c to produce the symbol c, which would then be returned. In the case of
(if(<= i 0)
(write "equals zero!") ; then
(reverse nL) ; else
)
you're comparing whether i is less than or equal to zero, and if it is, you print equals zero, and if it's not, you (non-destructively) reverse nL and discard the result. Then you finish the function by making a call to triangle. It seems like you probably want to return the reversed nL when i is less than or equal to zero. Use cond instead, since you can have multiple body forms, as in:
(cond
((<= i 0) (write ...) (reverse nL))
(t (triangle ...)))
You could also use if with progn to group the forms:
(if (<= i 0)
(progn
(write ...)
(reverse nL))
(triangle ...))
Your other function has the same problem. If you want to return values in those first cases, you need to use a form that actually returns them. For instance:
(if (< n 1)
(list 1)
(if (= n 1)
(last l)
(bell #| ... |#)))
More idiomatic would be cond, and using list rather than l, which looks a lot like 1:
(cond
((< n 1) (list 1))
((= n 1) (last list))
(t (bell #| ... |#)))
Thank you all for the explanations. I eventually arrived at the code below. I realized that the if block worked something like..
(if (condition) (execute statement) (else execute this statement))
(defun bell(l n)
(if (< n 2)(last l)
(bell (triangle l (last l) 0) (- n 1))
)
)
(defun triangle(pL nL i)
(if(= i (list-length pL)) nL
(triangle pL (append nL (list (+ (nth i pL) (nth i nL)))) (+ i 1))
)
)
(write (bell (list 1) 10))
I'm a beginner and I am trying to teach myself Common Lisp and during my self-study I have written a function that I believe should work for recursive addition of two arguments. However, the function always fails. Why is that?
(defun sum (n m)
;;;Returns the sum of n and m using recursion
(cond ((eq m 0) n))
(sum (1+ n) (1- m)))
As I understand it, it should continually add 1 to n while decrementing m until m is 0 at which point, the recursive addition is complete
I think you have 2 simple typos:
one parenthesis too many and
missing t in your cond clause.
What you probably meant was:
(defun sum (n m)
(cond
((eq m 0) n) ; here you had one parenthesis too many
(t (sum (1+ n) (1- m))))) ; here you were missing the `t` symbol
It's really wierd use case to do such addition, but I'll explain you where is your mistakes:
(defun sum (n m)
;;;Returns the sum of n and m using recursion
(cond ((eq m 0) n)) ;; <= This line is ignored, you not returnin N.
(sum (1+ n) (1- m))) ;; <= this will be called forever
You should write:
(defun sum (n m)
"Recursively increment N and decrement M untill M = 0"
(if (= m 0) ;; don't use EQ for numbers, use EQL or =.
n
(sum (1+ n) (1- m)))) ;; Otherwise recursive call
Let's trace it to see how it works:
CL-USER> (sum 0 10)
0: (SUM 0 10)
1: (SUM 1 9)
2: (SUM 2 8)
3: (SUM 3 7)
4: (SUM 4 6)
5: (SUM 5 5)
6: (SUM 6 4)
7: (SUM 7 3)
8: (SUM 8 2)
9: (SUM 9 1)
10: (SUM 10 0)
10: SUM returned 10
9: SUM returned 10
8: SUM returned 10
7: SUM returned 10
6: SUM returned 10
5: SUM returned 10
4: SUM returned 10
3: SUM returned 10
2: SUM returned 10
1: SUM returned 10
0: SUM returned 10
10
If you'll take an advice - don't try to do such weird things with recursion, if you want to leard how to use it, try it for some natural-recursive cases like factorials, fibonacci, tree processing and such.