CS 342 Lecture -*- Outline -*- * Structural organization series of definitions (functions) invoked (interactively) by a command (expression) * Built-in types of Scheme ** Fundamental classifications *** atoms: string of characters beginning with letter, digit, or char other than "(" or ")" subdivided into booleans, symbols, strings, numbers, chars #t, #f, symbol, "string", 27.3, #\c, () *** lists: sequence of S-expressions enclosed by parentheses (atom turkey or), (), ((a b) c) *** S-expression: atom, or list atom, (a b), ((a b) c ()), () note that () is both a list and an atom, and same as #f in C-scheme ** symbol ---------------- (quote a) ; Value: A (symbol? (quote a)) ; Value: #T (eq? (quote a) (quote a)) ; Value: #T (eq? (quote a) (quote b)) ; Value: () (eq? (quote ()) #f) ; Value: #T ---------------- Notation: (quote a) is written 'a. *** quotation suppresses evaluation ---------------- (+ 3 4) ; Value: 7 (quote (+ 3 4)) ; Value: (+ 3 4) (quote (quote (+ 3 4)) ; Value: '(+ 3 4) --------------- quote not needed for "self-evaluating" atoms: numbers, strings, booleans 3 ; Value: 3 (quote 3) ; Value: 3 ** Boolean ; false represented by (), which can also be written #f, ; true represented by everything else, in particular #t ------------------ () ; Value: () #f ; Value: () #t ; Value: #T (not #t) ; Value: () (not #f) ; Value: #T ; suppose value of e1 is VAL-E1 and value of e2 is VAL-E2 (define e1 'val-e1) (define e2 'val-e2) (if #t e1 e2) ; Value: VAL-E1 (if #f e1 e2) ; Value: VAL-E2 ---------------- (and e1 e2) =def= (let ((ve1 e1)) (if (not (null? ve1)) e2 ve1)) (or e1 e2) =def= (let ((ve1 e1)) (if (null? ve1) e2 ve1)) *Note: 'if' is not strict (so neither is 'and' nor 'or')* *** Notation: conditional statement ---------------- (cond (#t e1)) ; Value: VAL-E1 (cond (#f e1)) ; Value: () --------------- (cond (e11 e12) ... (en1 en2)) =def= (if e11 e12 (cond (e21 e22) ... (en1 en2))) (cond (e1 e2) ... (else en2)) =def= (cond (e1 e2) ... (#t en2)) example: (cond (e1 e2) (else e3)) =def= (if e1 e2 e3) ** lists cons, car, cdr, null?, equal? --------------- ; suppose value of x is X and value of y is Y (define x 'X) (define y 'Y) ; suppose l is the list (A B C), l2 is list (D E) (define l '(A B C)) (define l2 '((D) (E))) (cons x '()) ; Value: (X) (car (cons x l)) ; Value: X (cdr (cons x l)) ; Value: (A B C) (pair? (cons x l)) ; Value: #T (pair? '()) ; Value: () (null? '()) ; Value: #T (null? (cons x l)) ; Value: () (equal? '() '()) ; Value: #T --------------- (equal? (cons x l) (cons y l2)) =def= (and (eqv? x y) (equal? l l2)) ; Value: () (list 'a 'b 'c) =def= (cons 'a (cons 'b (cons 'c '()))) ; Value: (A B C) *** Notation --------------- '() ; Value: () '(a b c) ; =def= (quote (a b c)) ; Value: (A B C) --------------- `(e1 e2) =def= (quasiquote (e1 e2)) ; Value: (E1 E2) `(,e1 ,e2) =def= (quasiquote ((unquote e1) (unquote e2))) ; Value: (VAL-E1 VAL-E2) `(,@l ,l) =def= (quasiquote ((unquote-splicing l) (unquote l))) ; Value: (A B C (A B C)) ------------- (caar l2) ; =def= (car (car l2)) ; Value: D (cadr l2) ; =def= (car (cdr l2)) ; Value: (E) ------------- etc. *** Dotted pairs (cons cells, trees): *draw graphical representation* '(a . b) =def= (cons 'a 'b) ; Value: (A . B) '(a . (b . ())) ; Value: (A B) lists always end in (), dotted pairs don't necessarily. *** Examples **** normal recursion on lists, ask if null? first -------- (define (length-recursive x) (if (null? x) 0 (+ 1 (length-recursive (cdr x))))) --------- **** tail recursive: last call in function is recursive, no deferred operations: --------- (define (length-tail-recursive x) (define (length-iter a count) (cond ((null? a) count) (else (length-iter (cdr a) (+ 1 count))))) (length-iter x 0)) --------- *show execution of (length-x '(a b c)) Tail-recursive function can be interpreted using only constant amount of space. Like iteration. **** additional operations on lists ***** append -------- (define (append-recursive x y) (cond ((null? x) y) (else (cons (car x) (append-recursive (cdr x) y))))) --------- No good way to do append tail-recursively (without reversing first argument). ***** reverse --------- (define (reverse-recursive x) (cond ((null? x) x) (else (append (reverse-recursive (cdr x)) (list (car x)))))) (define (reverse-tail-recursive x) (define (reverse-iter y res) (cond ((null? y) res) (else (reverse-iter (cdr y) (cons (car y) res))))) (reverse-iter x '())) ---------- *** Lists can represent other data structures **** arrays -easy (although built-in to most dialects) **** variants - tag (in car) + object (in rest of list) **** records - association lists (or property lists) ***** Association lists (records) list of pairs (each of which represents a key-value association) first association in list is one found by assoc (duplicates allowed) ----------- (define (acons key datum alist) (cons (cons key datum) alist)) (define (assoc key alist) (cond ((null? alist) '()) ((and (pair? (car alist)) (equal? key (caar alist))) (car alist)) (else (assoc key (cdr alist))))) ; tail recursive ----------- *** Other important type: procedures, will be discussed later ** Eq? vs. eqv? vs. equal? *** eq? compares symbols, booleans, and lists for object identity (same list pointer, name) *** eqv? compares as eq? for symbols, booleans, lists, but guaranteed to work for numbers and strings *** equal? compares structure, using eqv? as basis for comparing atoms. *in functional programs, almost always want to use equal? instead of eq?