30 May Section

static vs. dynamic scoping

Given these definitions in an imaginary, dynamically scoped variant of Scheme...

(define m 50)
(define n 100)

(define (hardy)
   (display (list "In Hardy, n=" n))
   (newline))

(define (laurel n)
   (display (list "In Laurel, m=" m))
   (newline)
   (display (list "In Laurel, n=" n))
   (newline)
   (foo!)
   (hardy))

(define (foo!)
  (set! n (+ 1 n)))

...what would this code output using dynamic scoping rules?

(display (list "In main program, n=" n))
(newline)
(laurel 1)
(hardy)

Select below to reveal answer:

(In main program, n= 100)
(In Laurel, m= 50)
(In Laurel, n= 1)
(In Hardy, n= 2)
(In Hardy, n= 100)

side effects in Scheme

For simplicity's sake, your function definitions may assume that their arguments are non-empty lists, i.e., no error-checking.

  1. Write a function dupe-first in pure functional style that takes a list and returns a copy of the list with the first element duplicated, e.g., (dupe-first '(1 2 3)) => (1 1 2 3).

    hidden answer:

    (define (dupe-first l)
      ;; prepend copy of first element to list 
      (cons (car l) l))
    
  2. Write a side-effecting version dupe-first! of the same function that modifies the actual analogously. Refer to this sample usage:

    (define x '(1 2 3))
    x => (1 2 3)
    (dupe-first! x)
    x => (1 1 2 3)

    hidden answer:

    (define (dupe-first! l)
      (define n (list (car l)))	; create new list node...
      (set-cdr! n (cdr l))		; w/ next pointing at l's second node
      (set-cdr! l n)		; splice new node after first
      l)				; return modified list (though not necessary)
  3. Write similar pure functional and side-effecting versions of a function that removes the second element of the list, as in these examples:

    (define x '(1 2 3))
    (remove-second x) => (1 3)
    x => (1 2 3)
    (remove-second! x) => (1 2 3) ;; or "Unspecified return value" is OK
    x => (1 3)

    hidden answer:

    (define (remove-second l)
      ;; prepend first element to cdr of
      (cons (car l) (cddr l)))
    
    (define (remove-second! l)
      ;; splice out second node by setting first node's cdr to third node
      (set-cdr! l (cddr l))
      l)
  4. It would not be very easy to write a side-effecting function remove-first! that removes the first element of a list. Explain why this is the case.

    hidden hint:

    It has to do with the way parameters are passed in Scheme.

    By the way, the pure functional version is easy to write. Don't run your brain too hard: It rhymes with "footer."