150 likes | 249 Views
Data Abstraction. Programming Language Essentials 2nd edition Chapter 2.3 Representation Strategies for Data Types. Goals. abstract datatype makes program independent of concrete representation look at implementation strategies
E N D
Data Abstraction • Programming Language Essentials • 2nd edition • Chapter 2.3 Representation Strategies for Data Types
Goals • abstract datatype makes program independent of concrete representation • look at implementation strategies • environment maps a finite set of Scheme symbols to values taken from all Scheme values • e.g., values of variables • e.g., lexical addresses of symbols
Environment Interface • (empty-env) • constructor, represents an empty environment • (apply-env environmentsymbol) • observer, applies a representation to a symbol, returns associated value • (extend-env symbol-list value-list environment) • constructor, represents an environment which returns given values for given symbols and defaults to old environment otherwise
Example • (define dxy-env • (extend-env '(d x) '(6 7) • (extend-env '(y) '(8) • (empty-env)))) • (apply-env dxy-env 'x) • has to return 7 • $ cd code/2; make 2.3.2 2.3.3
Represent values as procedures • (define empty-env ; returns function that fails • (lambda () • (lambda (s) (error 'apply-env "No binding" s)) • ) ) • (define extend-env ; returns function returning vals • (lambda (syms vals env) ; or asks env • (lambda (sym) • (let ((pos (list-find-position sym syms))) • (if (number? pos) • (list-ref vals pos) • (apply-env env sym) • ) ) ) ) ) • (define apply-env • (lambda (env sym) (env sym)) • )
Searching a linear list • (define list-find-position ; returns pos >= 0 or #f • (lambda (s list) ; of s in list • (list-index (lambda (x) (eqv? x s)) list) • ) ) • (define list-index ; returns pos >= 0 or #f • (lambda (p? l) ; where p? is true in l • (cond • ((null? l) #f) • ((p? (car l)) 0) • (else • (let ((list-index-r (list-index p? (cdr l)))) • (if (number? list-index-r) • (+ list-index-r 1) • #f • ) ) ) ) ) )
How-to abstract using procedures • if client uses data-type only by way of values returned by procedure calls: • for each lambda expression returning such a value: embed it into a constructor which takes the free variables as parameters. • replace the lambda expression in the client by invoking the constructor. • define an observer apply-x to invoke the result returned by the constructor. • replace every value by invoking apply-x.
Represent values using syntax trees • env-rep: '(' 'empty-env' ')' • empty-env-record • | '(' 'extend-env' '(' 'Symbol'* ')' • '(' 'Value'* ')' env-rep ')' • extended-env-record (syms vals env)
Abstract syntax tree • (define-datatype environment environment? • (empty-env-record) • (extended-env-record • (syms (list-of symbol?)) • (vals (list-of scheme-value?)) • (env environment?) • ) ) • (define scheme-value? (lambda (v) #t))
Constructors • (define empty-env • (lambda () • (empty-env-record) • ) ) • (define extend-env • (lambda (syms vals env) • (extended-env-record syms vals env) • ) )
Observer • (define apply-env • (lambda (env sym) • (cases environment env • (empty-env-record () • (error 'apply-env "No binding" sym)) • (extended-env-record (syms vals env) • (let • ((pos • (list-find-position sym syms))) • (if (number? pos) • (list-ref vals pos) • (apply-env env sym) • ) ) ) ) ) )
How-to abstract using syntax trees • if client uses data-type only by way of values returned by procedure calls: • for each lambda expression returning such a value: create one variant with one field per free variable in lambda expression. • use define-datatype with those variants. • replace the lambda expression in the client by invoking the constructor. • define an observer apply-x based on cases where the bodies of the lambda expressions are the bodies of the consequents of cases. • replace every value by invoking apply-x.
Represent environment with lists • env-rep: '()' • | '(' '(' '(' 'Symbol'* ')' '.' • '#(' 'Value'* ')' ')' '.' env-rep ')' • ribcage a b c 1 2 3 d e 4 5
Constructors • (define empty-env • (lambda () '()) • ) • (define extend-env • (lambda (syms vals env) • (cons • (cons syms (list->vector vals)) • env • ) ) ) • $ cd code/2; make 2.3.4
Observer • (define apply-env • (lambda (env sym) • (if (null? env) • (error 'apply-env "No binding" sym) • (let* • ((syms (car (car env))) • (vals (cdr (car env))) • (pos (list-find-position sym syms)) • ) • (if (number? pos) • (vector-ref vals pos) • (apply-env (cdr env) sym) • ) ) ) ) )