0
votes

I have a requirement to return the last negative number in a list, using a recursive procedure. Right now I have a recursive procedure that returns all negative numbers in the list.

(define returnLastNeg
  (lambda (lst) 
    (if (null? lst) 
        '() 
        (if (positive? (car lst)) 
            (returnLastNeg (cdr lst))
            (cons (car lst) (returnLastNeg (cdr lst)))))))

calling it with (returnLastNeg'(1 -2 -3 4 -5 6)) returns

Output:

'(-2 -3 -5)

I need it to only return -5 though. I tried to modify my procedure to check to see if the last element in the list is positive. If it is, I want to remove the last element and then call the procedure again. But when I do that I get an error (below)

Modified procedure:

(define returnLastNeg-modified
  (lambda (lst) 
    (if (null? lst) 
        '() 
        (if (positive? (last lst))
            (remove (last lst) (lst))
            (cons (car lst) (returnLastNeg-modified (cdr lst)))))))

ERROR:

application: not a procedure;
 expected a procedure that can be applied to arguments
  given: '(1 -2 -3 4 -5 6)
  arguments...: [none]
> 
1
Given that you appear to be using Racket, you could always just use drop-right from racket/list.Alexis King
@AlexisKing that gives me the same errormdo123
If lst is a list so that (last lst) works how it's a paradox that you also have (lst) in your code other places than the parameter list which clearly seems to try to run lst as if it evaluated to a procedure. lst cannot be both a procedure and a list so one of them will fail.Sylwester

1 Answers

0
votes

A simpler approach would be with a helper procedure (called "sub") in this example:

(define returnLastNeg
  (lambda (lst)
    (define sub
      (lambda (lst last-neg)
        (if (null? lst)
            last-neg
            (let ((c (car lst)))
              (sub (cdr lst)
                   (if (negative? c) c last-neg))))))  
    (sub lst null)))

EDIT

Knowing that

(define <procedureName> (lambda (<params>) ... )

is the same as

(define (<procedureName> <params>) ... )

and reformatting a little, this becomes:

(define (returnLastNeg lst)

  (define (sub lst last-neg)
    (if (null? lst)
        last-neg
        (let ((c (car lst)))
          (sub (cdr lst) (if (negative? c) c last-neg)))))

  (sub lst null))

I hope it's clearer

  • last-neg gets set to null by the very last expression
  • the recursive call to sub has 2 parameters (split on 2 lines in the initial version, but newlines don't matter).

This is the same as the even shorter version

(define (returnLastNeg lst)
  (let sub ((lst lst) (last-neg null))
    (if (null? lst)
        last-neg
        (let ((c (car lst)))
          (sub (cdr lst) (if (negative? c) c last-neg))))))

using a so-called "named let".