jozefg's answer is right in pointing out that (cons? x)
is not the same as (not (empty? x))
, in general, because there are things (e.g., numbers) that are neither cons cells nor the empty list.
However, your variable was list-name
, so you may have some reason to expect that its value is, in fact a list. A list, in Scheme, is either:
- the empty list; or
- a cons cell whose
car
is the first
element of a list and whose cdr
is the rest
of the list.
Because of this, if you're writing a function that requires a list be passed in, then it does make sense to simply check for the trivial case (the empty list) with empty?
, and to assume, since you've required a list, that anything that doesn't match that case is a cons cell on which you can call cdr
and cdr
. This is because while
(cons? x) == (not (empty? x))
is not true of values in general, it is true for lists. That is, if you already know that lst
is a list, then
(cons? lst) == (not (empty? lst))
is true. There are a number of functions that do the same thing when we're talking about lists and cons cells. E.g., empty?
and null?
do the same thing, but they signal a slightly different intent on the part of the programmer. Similarly, car
and cdr
do the same thing as first
and rest
, but car
and cdr
signal that you might be treating something as a pair of two things, whereas first
and rest
clearly signal the intent that you're working with a list.
Your code, since it seems to expect a list, should probably be the following, since, for a list, if it's not the empty list, it must be a cons.
(define (f lst)
(cond
[(empty? lst) empty]
[else "do something]))
More generally, the code you write should depend on what kind of input you expect. E.g., in the first case, it's fine to check for empty, and assume a cons otherwise, because you're expecting a list. In the second case, you have to check for all the different kinds of things you might see.
(define (frob-list lst)
(cond
[(empty? lst) empty] ; arg is ()
[else ...])) ; arg is (x . y)
(define (frob-object obj)
(cond
[(null? obj) ...] ; arg is ()
[(cons? obj) ...] ; arg is (x . y)
[(number? obj) ...] ; arg is r
... ; arg is ...
[else ...])) ; else ...