Tom
Tom

Reputation: 35

Scheme: Return a list of positive values

So my input is some list l, and the goal of the function is to take all of the positives and make a new list with just these positive values. This is what I've currently got:

(define (positives l)
  (define (poscheck l)
    (cond ((negative? (car l)) '())
          ((null? l) '())
          (else (poscheck (cdr l)))))
(list (poscheck l)))

For some reason, it keeps telling me that it's given an empty list when checking (car l). I'm not exactly sure what it's picking up on for the error. Any help with fixing this code would be appreciated.

Upvotes: 0

Views: 2915

Answers (3)

Sylwester
Sylwester

Reputation: 48745

So I like to check the simple things first.

(positives '()) ; ==> ERROR

So for a empty list you first check if the first element is negative.. But an empty list must clearly be checked before you can further check if the first element is smoething.

(positives '(-1 2 3)) ; ==> (())

If the first element is negative the helper stops and is done.. Shouldn't it just skip the first element?

The last observation is that in the case a number is positive you should add it to the answer by consing the element to the recursion of the rest of th elist. What it does now is what should happen if in fact the element is negative.

There is no reason to wrap the result in list. If poscheck returns (1 2 3) then positives would make it ((1 2 3)).

To wrap it up it should look something like this with the ... filled in:

(define (positives lst)
  (cond ((null? lst) '())
        ((negative? (car lst)) (positives ...))
        (else (cons ... (positives ...)))))

Technically this assumes zero as positive. By switching places in the two last terms and using positive? it would omit zero.

Upvotes: 2

rnso
rnso

Reputation: 24535

Using named let may help clarify the process of getting only positives (inline comments are added):

(define (onlyPositives L)
  (let loop ((L L)              ; start with full list
             (ol '()))          ; and an empty outlist
    (cond
      [(empty? L)               ; if end of list reached, return outlist (reversed since cons adds at head of list); 
       (reverse ol)]
      [(positive? (car L))      ; if first item is positive, loop with rest of list and first item added to outlist; 
       (loop (cdr L)
             (cons (car L) ol))]
      [else                     ; else loop with rest of list without adding item to outlist; 
       (loop (cdr L)
             ol)]
      )))

Upvotes: 1

David Merinos
David Merinos

Reputation: 1295

The first answer works just fine, however:

;; poscheck function. Use it to assign positive lists from another lists.
;; example (define positives (poscheck '(1 2 -4 -5 0 3) '()))
;; positives -> '(3 2 1)
(define (poscheck l r)
  (cond ((empty? l) r)
        ((positive? (car l)) (poscheck (cdr l) (cons (car l) r )))
        (else (poscheck (cdr l) r))))

In this answer, I use tail-recursion, which basically means using a variable to store the final result among many recursive calls.

We want to think about what's the worst case scenario to make it our first option in the cond function, in this case, the worst that could happen (making car fail) is that the list is empty (check what (car '()) does). So we want to stop there. If the list is empty it means that we've gone through all of our items to check.

Our next case is that which happens when the current item (car l) is positive, which means we want it to be in our final result, so we add it in our result-storing variable to use it in the next recursive call by doing

(poscheck (cdr l) (cons (car l) r ))

This calls the function with the rest of the list but saving what I just examined.

The last case would be that which happens when the current item is not desired in our final list, so we just ignore it by calling the function with the rest of the list and the same result-storing variable without mutating it. We do that with:

(poscheck (cdr l) r)

And that's pretty much of it, no map, no filter, no other weird functions (for us newbs in DrRacket).

Hope it was helpful for you, if you've any doubts don't hesitate in asking!

Upvotes: 1

Related Questions