I'm writing a simple function that recursively checks if x
(a list) is an element of remaining
(list of lists).
Somehow, the #f
return from innermost frame doesn't properly bubble up to the top:
#lang sicp
(define (was_seen? remaining x)
(cond ((null? remaining) #false)
((eq? (car remaining) x) #true)
((was_seen? (cdr remaining) x))
)
)
; test variables
(define seen (list(list 'a)))
(define z (list 0))
; now the test
(was_seen? seen z)
; expected: #f; returns blank (evaluated to #void when seen via debugger)
(was_seen? (cdr seen) z)
; expected: #f; returns #f as it should.
; This is what the inner (recursive) call - correctly - evaluates to.
; It's just that this #f doesn't get properly returned to the global caller?
It must be something stupid simple, but I cannot find what. Any help would be appreciated.
cond
returns the value from the body of the first clause whose condition is truthy (i.e. not #f
), or the value of the else
clause if none of them are truthy.
If none of the conditions are truthy, and there's no else
clause, it returns #void
.
In your case, none of the conditions is ever true, since the recursive call is false.
Change the last clause to be an else
clause so the value of the recursive call will be returned.
(define (was_seen? remaining x)
(cond ((null? remaining) #false)
((eq? (car remaining) x) #true)
(else (was_seen? (cdr remaining) x))
)
)
You may think you were depending on the shortcut that the value of the condition is returned if there's no body in the clause. But that only happens when the condition is truthy, so that this is the clause that's going to return a value. It doesn't apply when the condition is false.