Functional Problem Solving (CSC 151 2015F) : EBoards

CSC151.01 2015F, Class 30: Other Forms of List Recursion


Overview

Preliminaries

Admin

Upcoming Work

Extra Credit Opportunities

Academic

Peer Support

Questions

Recursion, revisited

Two minutes with partner:

Key Ideas:

When is it useful to have a helper function? Here's an example: Sum

Often makes it easier to think about solving the problem. Also other issues that we'll discuss in a few minutes.

    (define sum
      (lambda (lst)
        (sum-kernel lst 0)))

    (define sum-kernel
      (lambda (lst running-sum)
        (if (null? lst)
            running-sum
            (sum-kernel (cdr lst) (+ (car lst) running-sum)))))

What kinds of parameters can you use for recursion? Can you just do recursion on lists?

We can do recursion on all sorts of things. You'll learn about recursion with numbers tonight!

Why does helper recursion give us lists backwards?

    (define select-odd-1
      (lambda (lst)
        (cond 
          [(null? lst)
           null]
          [(odd? (car lst))
           (cons (car lst)
                 (select-odd-1 (cdr lst)))]
          [else
           (select-odd-1 (cdr lst))])))

    (define select-odd-2
      (lambda (lst)
        (select-odd-kernel lst null)))

    (define select-odd-kernel
      (lambda (lst odds-so-far)
        (cond
          [(null? lst)
           odds-so-far]
          [(odd? (car lst))
           (select-odd-kernel (cdr lst)
                              (cons (car lst) odds-so-far))]
          [else
           (select-odd-kernel (cdr lst)
                              odds-so-far)])))

    (select-odd-2 '(5 2 1 3 4 7))
    -> (select-odd-kernel '(5 2 1 3 4 7) null)
    -> (select-odd-kernel '(2 1 3 4 7) '(5))
    -> (select-odd-kernel '(1 3 4 7) '(5))
    -> (select-odd-kernel '(3 4 7) '(1 5))
    -> (select-odd-kernel '(4 7) '(3 1 5))
    -> (select-odd-kernel '(7) '(3 1 5))
    -> (select-odd-kernel '() '(7 3 1 5))
    -> '(7 3 1 5)

Can we do the non-helper version?

    (define select-odd-1
      (lambda (lst)
        (cond 
          [(null? lst)
           null]
          [(odd? (car lst))
           (cons (car lst)
                 (select-odd-1 (cdr lst)))]
          [else
           (select-odd-1 (cdr lst))])))

    (select-odd-1 '(3 4 1 2 5))
    -> (cons (car '(3 4 1 2 5)) (select-odd-1 (cdr '(3 4 1 2 5))))
    -> (cons 3 (select-odd-1 (cdr '(3 4 1 2 5))))
    -> (cons 3 (select-odd-1 '(4 1 2 5)))
    -> (cons 3 (select-odd-1 (cdr '(4 1 2 5))))
    -> (cons 3 (select-odd-1 '(1 2 5)))
    -> (cons 3 (cons (car '(1 2 5)) (select-odd-1 (cdr '(1 2 5)))))
    -> (cons 3 (cons 1 (select-odd-1 '(2 5))))
    -> (cons 3 (cons 1 (select-odd-1 (cdr '(2 5)))))
    -> (cons 3 (cons 1 (select-odd-1 '(5))))
    -> (cons 3 (cons 1 (cons (car '(5)) (select-odd-1 (cdr '(5))))))
    -> (cons 3 (cons 1 (cons 5 (select-odd-1 null))))
    -> (cons 3 (cons 1 (cons 5 null)))
    -> (cons 3 (cons 1 '(5)))
    -> (cons 3 '(1 5))
    -> '(3 1 5))

When we use helpers with lists, should we reverse them at the end?

Probably. It depends on the goals of the procedure.

    (define select-odd-2
      (lambda (lst)
        (reverse (select-odd-kernel lst null))))

    (define select-odd-kernel
      (lambda (lst odds-so-far)
        (cond
          [(null? lst)
           odds-so-far]
          [(odd? (car lst))
           (select-odd-kernel (cdr lst)
                              (cons (car lst) odds-so-far))]
          [else
           (select-odd-kernel (cdr lst)
                              odds-so-far)])))

If the goal was to reverse, then probably not

Why is (and) #t and (or) #f?

(or ...) is #t if any of its parameters are true.
(or ...) is false otherwise. None of the parameters to (or) is true.

(and ...) is #f if any of its parameters are false. (and ...) is #t (or truish) otherwise. None of the parameters to (and) are false. So it must be true.

Key ideas from pre-break lab

Two minutes with partner:

What's wrong?

How to fix?

Lab

Not done. Please read over and send questions!