---
title: Eboard 26  Naming local recursive procedures
number: 26
section: eboards
held: 2019-04-08
link: true
---
CSC 151 2019S, Class 26:  Naming local recursive procedures
===========================================================

_Overview_

* Preliminaries
    * Notes and news
    * Upcoming work
    * Extra credit
    * Questions
* Some notes on efficiency
* Some notes on named let
* Lab

Preliminaries
-------------

### News / Etc.

* Welcome to prospective students!
    * You get the opportunity to ask questions of the 151 students!
* Mentor sessions Wednesday 8-9 p.m., Thursday 8-9 p.m., Sunday 5-6 p.m.
* Let me know if you want to change your categorization (methodical,
  in-between, zoomer) on the next assignment.  
    * I've also lost cards for RC, RL, and KS, so email me your prefs.

### Upcoming work

* [Homework 7](../assignments/assignment07) due Tuesday.  
* Friday's quiz: Recursion
* Reading for Wednesday: 
  [Pairs and pair structures](../readings/pairs)
* Flash cards Wednesday night: Recursion
* Lab writeup: Exercise TBD
    * CSC 151.01 2019S Writeup for class 26 (Your Names)

### Extra Credit

_I would certainly appreciate suggestions of other extra credit activities
(preferably via email)._

#### Extra credit (Academic/Artistic)

* CS Table Tomorrow - The Autocrat's New Toolkit

#### Extra credit (Peer)

* Track and Field at Monmouth this coming weekend.
* Women's Golf at Illinois Wesleyan this coming weekend.

#### Extra credit (Wellness)

#### Extra credit (Wellness, Regular)

* 30 Minutes of Mindfulness at SHACS (SHAW) every Monday 4:15-4:45
* Any organized exercise.  (See previous eboards for a list.)
* 60 minutes of some solitary self-care activities that are unrelated to
  academics or work.  Your email reflection must explain how the activity
  contributed to your wellness.
* 60 minutes of some shared self-care activity with friends. Your email
  reflection must explain how the activity contributed to your wellness.

#### Extra credit (Misc)

* Participate in Kinetic Sculpture Competition: Saturday the 27th
    * You'll need to build your sculpture in advance
* Wednesday the 10 at 4pm on Mac Field: Giant Laurel Leaf.  (Free t-shirt!)
* Scarlet and Give Back Day next Wednesday/Thursday (I think).  If you
  don't have money to donate, let me know and I will give you $5 on
  Monday to donate.  (That does commit you to donating and to writing
  something.)

### Other good things 

### Questions

_If we have a function in the output, what happens?  For example,
when do the addition and call to `list` get evaluated in the following?__

        (define function-kernel
          (lambda (so-far remaining)
            (write (list 'kernel so-far remaining))
            (newline)
            (if (null? remaining)
                so-far
                (kernel (+ 1 so-far) (cdr remaining)))))

> General rule in Scheme: Evaluate all of the parameters before
  calling the function.  (+ (* 2 3) (- 4 5)).

> Applying that general rule, we do the (+ 1 so-far) before we recurse
  we do the cdr before we recurse, and we build the list before we write.

> Is there a way to show it undone?

_Can we see an expression being built up?_

> If you do something strange to build it, as in the following.

	(define function-kernel
	  (lambda (computation so-far remaining)
	    (write (list 'kernel computation so-far remaining))
	    (newline)
	    (if (null? remaining)
	        so-far
	        (function-kernel (list '+ 1 computation) (+ 1 so-far) (cdr remaining)))))

_You just said that "we evaluate the parameters and then apply the procedure".  Are there exceptions to that?_

> Yes.  `if`, `and`, `or` are all exceptions.  `if` evaluates the first
  parameter and then decides which of the other two to evaluate.  `or`
  evaluates one at a time until it hits truish (or runs off the list),
  `and` evaluates one at time until it hits #f (or runs off the list).

> `cond`, `lambda`, `quote`

_Do we have to document problem 8 on HW 7?_

> Yes.  Documentation is good for your soul.  Or brain.  Or something.

Some notes on efficiency
------------------------

### One version of `smallest`

   (define smallest
     (lambda (lst)
       (cond
         [(null? (cdr lst))
          (car lst)]
         [(< (car lst) (smallest (cdr lst)))
          (car lst)]
         [else
          (smallest (cdr lst))])))

Observation: If the list is ordered from largest to smallest, the amount
of time doubles each time we add an element.  25 elements take about 1
second, 35 elements would take about 1000 seconds, 45 elements would take
1000000 seconds (over 11 days).

Why?  If it's in descending order, we always hit the else statement.  The
else statement is contributing to the cost.  Because we recurse *twice*.
And those also have to recurse twice.  And so on and so forth.

How can we fix this?

Option 1: Completely change the structure to our "reduce" structure"

    (define smallest
      (lambda (lst)
        (if (null? (cdr lst))
            (car lst)
            (min (car lst) (smallest (cdr lst))))))

Option 2: Try using and and or?  (Still needs work.)

Option 3: Use `let`.

    (define smallest
      (lambda (lst)
        (if (null? (cdr lst))
            (car lst)
            (let ([smallest-in-cdr (smallest (cdr lst))])
              (if (< (car lst) smallest-in-cdr)
                  (car lst)
                  smallest-in-cdr)))))

Option 4: Use a helper procedure (with named let)

_See below_.

Morals: If you can avoid it, don't have two identical recursive calls in 
the same procedure.  (More generally, try to avoid identical calls of any
sort in your procedure.)  `let` is your friend.

### Reversing

    (define my-reverse
      (lambda (lst)
        (if (null? lst)
            null
            (append (reverse lst) (list (car lst))))))

Morals

Some notes on named let
-----------------------

Named let is designed for when you want tail-recursive helper procedures.

When you think about tail-recursive helpers, you have

* Names of columns (e.g., remaining and so-far for `smallest`)
* Initial values for the columns (e.g., (cdr lst) and (car lst))
* Rule for updating

In named lets

        (let NAME ([column1 init1]
                   [column2 init2]
                   [column3 init3]
                   ...)
           (if BASE-CASE-TEST
               base-case
               (NAME (update column1) (update column2) ...)))

    (define smallest2
      (lambda (lst)
        (let kernel ([remaining (cdr lst)]
                     [smallest-so-far (car lst)])
          (if (null? remaining)
              smallest-so-far
              (kernel (cdr remaining)
                      (min smallest-so-far (car remaining)))))))

Lab
---

No lab writeup today.
