racket - Scheme - Using cons properly to create lists -
i've been trying solve exercise 2.20 of sicp, "dotted-tail" notation introduced. problem that, instead of returning proper list results, function returns nested list. know there wrong way i'm calling cons, still have no clue of how solve issue.
so here function:
(define (same-parity first . items) (define (speccar items) (cond ((null? items) 2) ((not (pair? items)) (modulo items 2)) (else (modulo (car items) 2)))) (define (iter-parity first items result) (let ((parityfirst (modulo first 2)) (samepar (speccar items))) (if (null? items) result (if (= parityfirst samepar) ;; next line problem is... (iter-parity first (cdr items) (cons (list result) (list (car items)))) (iter-parity first (cdr items) result))))) (iter-parity first items first))
test:
(same-parity 1 2 3 4 5) ((((1) 3)) 5)
now, i've read following answers deal similar problem:
cons element list vs cons list element in scheme
how use 'cons' without generating nested lists in scheme?
they make clear problem coming from, how 1 go implement proper solution? and, if possible, correct way of "thinking" in scheme avoid these traps/pitfalls?
you're incorrectly building output list - remember: first argument cons
should current element , second argument, result list.
also, given you're using tail recursion, you'll have reverse
output @ end preserve same order in original list. try this:
(define (same-parity first . items) (define (speccar items) (cond ((null? items) 2) ((not (pair? items)) (modulo items 2)) (else (modulo (car items) 2)))) (define (iter-parity first items result) (let ((parityfirst (modulo first 2)) (samepar (speccar items))) (if (null? items) (reverse result) (if (= parityfirst samepar) (iter-parity first (cdr items) (cons (car items) result)) (iter-parity first (cdr items) result))))) (iter-parity first items (list first)))
the above solution can simplified if use built-in procedures (don't reinvent wheel!). recommended way write programs in scheme - adhering functional style:
(define (same-parity head . tail) (if (even? head) (filter even? (cons head tail)) (filter odd? (cons head tail))))
either way, works expected:
(same-parity 1 2 3 4 5) => '(1 3 5)
Comments
Post a Comment