Skip to main content

Class 42: Higher-Order Procedures, Revisited

Held:

We revisit the topic of *higher-order procedures, one of the most important techniques in languages like Scheme. Higher-order procedures are procedures – like map, left-section, or compose – that take other procedures as parameters, return other procedures as values, or both.*

Preliminaries

Overview

  • Some program design principles
  • Thinking about repetition
  • Procedures as first-class values

Updates

News / Etc.

  • New partners! (You’ll keep your partner tomorrow, too.)

Upcoming Work

  • Lab writeup: TBD.
  • Reading for Wednesday: Files in Scheme
  • Exam 3
    • Exam due TONIGHT
    • Epilogue due tomorrow night (earlier is better)
  • Project Proposals due next Monday evening (artworks Tuesday).

Extra credit (Academic/Artistic)

  • Paul Bendich ‘01 talk on Data Science, Today, 11:00 a.m., somewhere in Math.
  • Any of the Research, Scholarship, and Creative Activity Symposium events April 17-20.
  • Quince Contemporary Vocal Ensemble. 7:30 p.m., Wednesday, April 19, Sebring-Lewis.
  • #robinhoodfail: The Ethics of Public Scholarship and the Digital Liberal Arts, Thursday, 7:30 pm, JRC 101.

Extra credit (Peer)

  • Any of the Research, Scholarship, and Creative Activity Symposium events that involve your classmates, April 17-20. (No double dipping!)
  • Art House Arts Fest on April 22nd.

Extra credit (Misc)

None right now.

Other good things to do

  • If you participate in Thursday’s festivities, be moderate.
  • Dag Field Day, Saturday, April 29, noon-5pm, in the Club Athletic Field.

Background: Guiding Principles

  • Write less, not more
    • It (usually) makes you faster.
    • It (usually) makes your code more readable.
    • It (usually) makes your code easier to maintain.
  • Refactor
    • Don’t write repetitious code
    • If you are programming by copy-paste-change, you’re probably wasting time.
  • Name appropriately
    • Good names for things that need names
    • No names for things that don’t need names

Background: The Value of Repetition

The following is variant of something my colleague John Stone says …

You learn from reading.

  • The first time you read a new procedure structure (such as recursion over a list), you learn something.
  • The second time you read the same structure, you learn something else.
  • The third time, you learn a bit more.
  • After that, reading doesn’t give much benefit.

You learn from writing.

  • The first time you write the same structure, you learn something more about that structure
  • The second time, you learn even more.
  • The third time, you learn a bit more.
  • After that, there’s almost no benefit.

So … extract the common code so you don’t have to write it again.

Procedures as First-Class Values

  • We’ll look at one way to achieve our guiding principles and write common code.
  • The big picture ideas:
    • You can write procedures (like map) that take other procedures as parameters.
    • You can write procedures (like left-section and compose) that return other procedures.
    • Doing so makes your code better.
  • Procedures are, in effect, yet another kind of value. What are the questions we normally ask about new types of values?
  • Taking a procedure as a parameter is easy. You just include it as a normal parameter and use it as a normal procedure.
(define apply-to-2-and-3
  (lambda (proc)
    (proc 2 3)))
  • Returning procedures is a bit harder. You usually just return an anonymous procedure. That means you’ll have multiple lambdas.
(define adder
  (lambda (n)
    (lambda (x)
      (+ x n))))
(define inc (adder 1))

Old Notes

The following are notes I wrote for past versions of the course. I probably won’t discuss any/all in class.

Two Motivating Examples

  • all-real? and all-integer?
  • add-5-to-each and multiply-each-by-5

Procedures as Parameters

  • We’ve been writing it a lot.
  • Useful
  • Concise
  • Supports refactoring

Procedures as Return Values

  • Another way to create procedures (anonymous and named).
  • Strategy: Write procedures that return new procedures.
  • These procedures can take plain values as parameters:
(define redder
  (lambda (amt)
    (lambda (color)
      (rgb ...))))
  • How to think about this:
    • a procedure that takes amt as a parameter,
    • returns a new procedure that takes color as a parameter
  • Can also take procedures as parameters
  • One favorite: compose <>boxcode (define compose (lambda (f g) (lambda (x) (f (g x)))))

</pre>

  • Examples
    • sine of square root of x: (compose sin sqrt)
    • last element of a list: (compose car reverse)
  • Another: left-section
(define left-section
  (lambda (func left)
    (lambda (right)
      (func left right))))
(define l-s left-section)
  • Examples:
    • add two: (l-s + 2)
    • double: (l-s * 2)
  • Not mentioned int he reading, but there’s a corresponding right-section
(define right-section
  (lambda (func right)
    (lambda (left)
      (func left right))))
(define r-s right-section)

Encapsulating Control

  • Possible for complex common code, too (particularly control).
  • map is the standard example.
(define map
  (lamda (fun lst)
     (if (null? lst)
         null
         (cons (fun (car lst))
               (map fun (cdr lst))))))
  • Another issue: Checking the type of elements in a list
(define all-numbers?
  (lambda (lst)
    (or (null? lst)
        (and (pair? lst)
             (number? (car lst))
             (all-numbers? (cdr lst))))))
(define all-symbols?
  (lambda (lst)
    (or (null? lst)
        (and (pair? lst)
             (symbol? (car lst))
             (all-symbols? (cdr lst))))))
  • Common code
(define all
  (lambda (test? lst)
    (or (null? lst)
        (and (pair? lst)
             (test? (car lst))
             (all test? (cdr lst))))))

Concluding Comments

  • Yes, skilled Scheme programmers write this way.
    • It’s quick.
    • It’s clear (at least to skilled Schemers).
    • It reduces mistakes.
  • The ability to encapsulate control in this way is fairly unique to Scheme (well, to functional languages).
  • It’s one of the reasons we love it at Grinnell.
    • Or at least a reason I love it.