Reputation: 33
it should count the elements of a list, but says "*** - +: NIL is not a number"
(setq A '(2 3 4 3 2 6 7 8 4 3 5 6))
(defun big (A)
(if (not (null (car A))) (+ 1 (big (cdr A))) ) ;if the first element is not null, add 1 to the count of the elements to the rest of the list
)
(print (big A))
Upvotes: 3
Views: 144
Reputation: 38967
An IF
expression has either 2 or 3 arguments:
(if test something)
(if test something something-else)
When it only has 2 arguments, it is as-if the third argument, something-else
, was NIL. That means that the IF
expression evaluates to NIL when the test
expression is false. In your case, you have 2 arguments:
(defun big (A)
(if (not (null (car A)))
;; "then" branch (when condition is true)
(+ 1 (big (cdr A)))
;; no "else" branch (when condition is false)
))
So you know that sometimes a call to big
might return NIL
.
But, you also write:
(+ 1 (big (cdr A)))
This expression looks like (+ 1 x)
with x
being a call to big
, meaning that x
might evaluate to NIL in some cases. That's the case you hit with the debugger.
If you make sure the if
expression always return a number, by returning for example zero in the else branch, then you won't have the same error about trying to add a number to NIL
.
But then, you would still have other bugs, since you say that the function big
"should count the elements of a list". If you want to count the element of a list, you never need to look at the elements stored in the list, you only need to know that they exist.
When you write (car a)
, you are accessing the first element of the list. You then check if that value is non-nil, but it is perfectly valid to have a list filled with NIL values:
'(NIL NIL NIL)
That list has 3 elements, and at no point the fact that they are NIL should matter when counting them.
A recursive function working on a list typically needs to cover two cases, namely if the list is empty or not. You check if the current list is empty by calling (null list)
or (endp list)
(just doing (if list ... ...)
works too since NIL is the only false value).
Upvotes: 3
Reputation: 96454
The test for null car doesn’t do any good, cdr will return nil before car does.
You need a base case where you find you’re done and return something instead of recursing. Right now you don’t have that. Look at examples of simple recursive functions and see how they have a base case.
To count the elements in a list there are two cases:
The base case where the list is empty (return 0)
The recursive case where the list isn’t empty (return 1 + the count of the cdr of the passed in list)
Upvotes: 2