Imperative Programming



Test:

	Q1. Most got it right.

(lambda (x)
  (lambda (y)
    ((lambda (x)
       (x y))
     x)))



(lambda (z)
  ((lambda (a b c)
     (a (lambda (a) (+ a c)) b))
   (lambda (f x)
     (f (z x)))))





Q2. Few mistakes:

(lambda (x y)
  ((lambda (a)
     (x (a y)))
   x))

(lambda (x y)
  (lambda (a)
     ((x : 1 0) ((a : 0 0) (y : 1 1))))
  (x : 0 0))



(lambda (x) x)

(lambda (x) (x : 0 0))




Q2. 

(lambda 1
 (lambda 1
  (: 1 0)))

(lambda (x)
  (lambda (y)
    x))




extend-ff* 

Solved on page 94 in the textbook:

(define extend-ff*
  (lambda (sym-list val-list ff)
    (if (null? sym-lst)
        ff
        (extend-ff (car sym-list) (car val-list)
          (extend-ff*
	    (cdr sym-list)
	    (cdr val-list)
	    ff)))))



Beta-Conversion

((lambda (x)
   (lambda (y) (x y)))
 (y w))


==>

(lambda (z) ((y w) z))




((lambda (x) (x y))
 (lambda (y) (x y)))

==>

((lambda (y) (x y)) y)




(lambda (x)
  ((lambda (x) (y x)) z))

Not a Beta-redex

Only applications are beta-redexes


(define parse
  (lambda (datum)
    (cond
      [(number? datum) (make-lit datum)]
      [(symbol? datum) (make-varref datum)]
      [(if-exp? datum) (make-if

                         _(parse (cadr datum))_

                         _(parse (caddr datum))_

                         _(parse (cadddr datum))_)]

      [(pair? datum)
        (if (eq? (car datum) 'lambda)
          (make-lambda (caadr datum) (parse (caddr
                                            datum)))
          (make-app (parse (car datum)) 
                    (parse (cadr datum))))]
      [else (error 'parse 
                   "Invalid concrete syntax")]))) 
 



(define unparse
  (lambda (exp)
    (variant-case exp
      [lit (datum) datum]
      [varref (var) var]
      [if (test-exp then-exp else-exp)
        (list 'if 

            _(unparse test-exp)_

            _(unparse then-exp)_

            _(unparse else-exp)_)]
            
      [lambda (formal body)
        (list
          'lambda (list formal) (unparse body))]
      [app (rator rand)
        (list (unparse rator) (unparse rand))]
      [else (error 'unparse 
            "Invalid abstract syntax expression")])))
   



Leftmost reduction:

Since applicative-order reduction can be caught in 
an infinite loop 

((lambda (y) 3
  (lambda (x) (x x)) (lambda (x) (x x))))


Is there a reduction strategy which is guaranteed
to find the answer if it exists?

Answer: Yes ==> Leftmost reduction:

        reduce the Beta-redex whose left paren
        comes first.

Advantages:

       Guaranteed to find normal form.
Normal form: Expression has no Beta-redexes

Disadvantage: 
       Efficiency:



((lambda (x) (x (x y)))
  ((lambda (w) w) z))

==>

(((lambda (w) w) z) 
  (((lambda (w) w) z) 
   y))

==>

(z (((lambda (w) w) z) y))

==>

(z (z y))

IF we reduce the operand first, we need fewer
reductions:

((lambda (x) (x (x y)))
 ((lambda (w) w) z))

==>

((lambda (x) (x (x y))) z)

(z (z y))




Imperative programming:

Scheme so far has been purely 

FUNCTIONAL:
  AN EXPRESSION ONLY EVALUATED FOR ITS VALUE

Advantages:
  No other effects of evaluation need be
considered
  Many problems can be solved easily
  Easy to reason about functional programs using
simple, but powerful, rules.

Disadvantages:
  Some cases, functional programming is awkward or
inefficient. 



Therefore:

IMPERATIVE PROGRAMMING:

operations are performed not to obtain a value but 
rather for some SIDE EFFECT on the computation

Broadly:
   ASSIGNMENT and I/O ops

Disadvantages:
   Difficult to reason about
   Beta/eta reductions not applicable

example:
  Leftmost reduction:
  Multiple copies of an operand made as part of a
  reduction. If further reduction of these copies
  involves side-effects, these will happen multiple
  times 


Start with sequencing and other imperative ops
needed for later.



Statement: evaluated/performed purely for side
effect 

Sequencing refers to the order in which
side-effects are performed.

  (begin e1 e2 ... en)

e1, e2, ..en evaluated in order.
value of begin expression is value of en


> (begin (display "Two plus two = ")
	 (display (+ 2 2)))
Two plus two = 44>
???

Values returned by display are not specified.
True for most side-effect procedures

extra 4 result of (display (+ 2 2)) the result
returned by en in (begin e1 ... en)
> (begin (display "Two plus two = ")
	 (display (+ 2 2)) 
	 (newline))
Two plus two = 4
()
> 

() returned by newline....?

What does our version of scheme do?



Let us define a for-each that is somewhat like map 
this applies a procedure in a left to right order 
on the members of a list.

(define for-each
  (lambda (proc lst)
    (if (null? lst)
	'done
	(begin
	  (proc (car lst))
	  (for-each proc (cdr lst))))))
  


> (displayln 2 "+" 2 "=" (+ 2 2))
2+2=4
> 



Implied sequencing in bodies of lambda, let,
letrec, and in consequents of
cond, case, and variant-case.....

(define displayln
  (lambda lst
      (for-each display lst)
      (newline)))


(define fact
  (lambda (n)
    (displayln "Entering fact with n = " n)
    (let ([ans (if (zero? n)
		   1
		   (* n (fact (sub1 n))))])
      (displayln "Returning from fact with " ans)
	 ans)))

> (fact 3)
Entering fact with n = 3
Entering fact with n = 2
Entering fact with n = 1
Entering fact with n = 0
Returning from fact with 1
Returning from fact with 1
Returning from fact with 2
Returning from fact with 6
6
> 

    

Sushil Louis
Last modified: Mon Oct 18 17:44:40 PDT 1999