Reputation: 39
I was writing a procedure that takes 2 expressions, and if there is a way for exp1 to be created through exp2 (when we replace exp2 with 'sss) using first, rest, cons, it then returns the code needed to produce exp1.
For example, this is what I would want to produce.
(find-in '(e r t) '(e t) ) => '(cons (first sss) (rest (rest sss)))
My code works for a lot of the test cases but when I ran through
(find-in '(a '(((v)) l) (f g)) '( (v g) l a))
It returns this error:
first: contract violation
expected: (and/c list? (not/c empty?))
given: 'g
The same error shows up when I try running this test case:
(find-in '(x a (x y)) '(z a (b)))
;supposed to return #f
This is my code so far:
(define find-in
(lambda (exp2 exp1)
(cond
((equal? exp2 exp1) 'sss)
((null? exp2) #f)
((not (list? exp2)) #f)
((find-in (first exp2) exp1) (repl 'sss '(first sss) (find-in (first exp2) exp1)))
((find-in (rest exp2) exp1) (repl 'sss '(rest sss) (find-in (rest exp2) exp1)))
(else (list? exp1)
(if
(and (find-in exp2 (first exp1)) (find-in exp2 (rest exp1)))
(list 'cons (find-in exp2 (first exp1)) (find-in exp2 (rest exp1)))
#f) #f))))
I am confused as to which condition I missed when I coded or if there was a logic error. What could have gone wrong?
Upvotes: 0
Views: 1289
Reputation: 91837
Your last clause doesn't look right to me. When you use the special else
token for your last clause, you are saying "There's nothing to test here, execute the body of this unconditionally if you've made it this far". Thus, your next expression, (list? exp1)
, is not a test as far as cond
is concerned: it is evaluated for side effects, and the results discarded. Then the next expression is also evaluated, whether exp1
was a list or not.
If you want to make this conditional on whether exp1
is a list, you should remove the excess else
at the beginning (and probably add an else
clause to the end to return #f
if none of your cases matched).
Upvotes: 1