Com S 342 meeting -*- Outline -*- * Sequencing and Imperative Programming (4.5) Q: What features of a language like Pascal or C haven't we discussed? at least side effects and I/O ** caution in reasoning ------------------------------------------ CAUTION: SIDE EFFECTS (4.5) def: a *side effect* is either (define called! (let ((count 0)) (lambda () (begin (set! count (+ count 1)) count)))) (called!) ==> 1 (list (called!) (called!)) ==>? def: an expression E is *referentially transparent* if ------------------------------------------ ... an assignment (change of a value), or input/output. (i.e., side effects are something other than the result of a procedure) Q: Can all side effects be thought of as assignments? yes, if you think of some location as the receptacle for the I/O. ... whenever it has a value, it always has the same value. Q: Are C++ expressions referentially transparent? Scheme expressions? ** sequencing (4.5.1) Q: In C, C++, or Pascal, what syntax is designed for side effects? =, :=, and also the semicolon C and C++ are also expresion-languages *** begin Q: Why is the semicolon needed? What does it mean semantically? How would you turn that into Scheme syntax? (semicolon e1 e2) recall that ; already starts a comment but then you'd have to write: (semicolon (semicolon e1 e2) e3) Better: (semicolon e1 ... en) But now let's remember that Scheme is an expression language. Is there any way we can turn this into an expression? have it return the last value. Just like that, but Scheme uses "begin" instead of semicolon ------------------------------------------ SEMICOLON AND ASSIGNMENT SYNTAX In Pascal In C/C++/Java x := x + 1; x = x + 1; y := y + x; y = y + x; z := x + y; z = x + y; procname := z + 1 return z+1; Example in Scheme: (begin (set! x (+ x 1)) (set! y (+ y x)) (set! z (+ x y)) (+ z 1)) Scheme Syntax: ::= (begin ) | (set! ) ::= {}* ::= ::= ------------------------------------------ Q: Does this affect scoping? Does it in other languges? *** implicit begin ------------------------------------------ SYNTACTIC SUGAR: IMPLICIT BEGIN problem: (define fact ; TYPE: (-> (number) number) (lambda (n) (begin (displayln "Entering fact with n = " n) (let ((ans (if (zero? n) 1 (* n (fact (- n 1)))))) (begin (displayln "Result from fact = " ans) ans))))) sugared form: (define fact ; TYPE: (-> (number) number) (lambda (n) (displayln "Entering fact with n = " n) (let ((ans (if (zero? n) 1 (* n (fact (- n 1)))))) (displayln "Result from fact = " ans) ans))) ------------------------------------------ ------------------------------------------ SYNTAX OF BODIES ::= {}* ::= of lambda, let, letrec, cond clause, case-clause is sugar for begin (lambda (formals) e1 ... en) = (lambda (formals) (begin e1 ... en)) (let (bindings) e1 ... en) = (let (bindings) (begin e1 ... en)) (cond (t1 e1 e2) (t2 e3 e4)) = (cond (t1 (begin e1 e2)) (t2 (begin e3 e4))) ------------------------------------------ Q: How would you change the fact procedure to use implicit begin? ------------------------------------------ WATCH OUT FOR SYNTAX ERRORS IN IF (if (zero? n) (displayln "n = " n) 1 (* n (fact (- n 1)))) SEMANTIC ERRORS IN COND (define sum ; TYPE: (-> ((list number)) number) (lambda (lon) (cond ((null? lon) 0) (else (cdr lon) (+ (car lon) (sum lon)))))) ------------------------------------------ Q: What are the errors? There's no implicit begin in an if, why? The use of implicit begin means the sum procedure isn't a syntax error although it goes into an infinite loop. ** order of evaluation Q: Are arguments to procedures evaluated in some particular order? not in Scheme How about in C? not defined Q: How about the order of side effect in (map display '(a fine day))? not determined, need to use for-each The following is MIT C-Scheme, which goes right to left! ------------------------------------------ ORDER OF EVALUATION % scheme 1 ]=> (+ (begin (write 'x) 3) (begin (write 'y) 4)) 1 ]=> (map write '(a fine day)) 1 ]=> (for-each write '(a fine day)) (define map ;; TYPE: (-> ((-> (T) S) (list T)) ;; (list S)) (lambda (f ls) (if (null? ls) '() (cons (f (car ls)) (map f (cdr ls)))))) (define for-each ;; TYPE: (-> ((-> (T) void) (list T)) ;; void) (lambda (f ls) ------------------------------------------ ... yx ; Value 7 ... dayfinea ;Value 1: (#[undefined-value] #[undefined-value] #[undefined-value]) ... afineday ; No value ... (if (not (null? ls)) (begin (f (car ls)) (for-each f (cdr ls)))))) Q: To write run-regression-tests, is map or for-each used?