Search code examples
lispmit-scheme

making same-parity function with g . w in mit scheme


I am trying to write a function that takes one or more integers and returns a list of all the arguments that have the same even-odd parity as the first argument, for example

(same-parity 1 2 3 4 5 6 7)->(1 3 5 7)
(same-parity 2 3 4 5 6)->(2 4 6). 

my code is

(define (same-parity g . w)
    (define (iter-parity items)
        (if (= (length items) 1)
            (if (= (remainder items 2) (remainder g 2))
                item
                '())
            (if (= (remainder g 2) (remainder (car items) 2))
                (cons (car items) (iter-parity (cdr items)))
                (iter-parity (cdr items)))))
    (cons g (iter-parity w)))

when try this (same-parity (list 1 2 3 4)), I got an error message: the object (), passed as the first argument to car, is not the correct type.

Can I somebody tell me what is going on?


Solution

  • Your code

    Here's a refactoring proposal, keeping with your basic structure:

    (define (same-parity g . w)
      (define filter-predicate? (if (odd? g) odd? even?))
    
      (define (iter-parity items)
        (if (null? items)
            '()
            (if (filter-predicate? (car items))
                (cons (car items) (iter-parity (cdr items)))
                (iter-parity (cdr items)))))
    
      (cons g (iter-parity w)))
    

    Note that it is more idiomatic

    • to use the procedures odd? and even? rather than remainder
    • to have as a base case when the list is empty, not when it has only one item (in your code this clearly avoids repetition as a positive effect).

    Also, since there is a built-in filter procedure in Scheme, you could express it as follows:

    (define (same-parity g . w)
      (cons g (filter (if (odd? g) odd? even?) w)))
    

    Your question

    As for your question regarding (same-parity (list 1 2 3 4)): you need either (as described in your specification) use your procedure like so

     (same-parity 1 2 3 4)
    

    or to use apply here:

    > (apply same-parity (list 1 2 3 4))
    '(1 3)
    

    because apply will transform (same-parity (list 1 2 3 4)) (1 parameter, a list) into (same-parity 1 2 3 4) (4 parameters).