Com S 342 meeting -*- Outline -*- * records (3.4) If you use scm342, you get define-record automatically ** declaration and use (3.4.1) This is applying the automation principle to data structures Will be one of our major tools in study of interpreters ------------------------------------------ RECORDS (3.4) problem: want to have named, random access to components of heterogeneous collection not random access: ((name "Tom") (age 22) (lang Scheme)) ((name "Sally") (age 23) (lang C++)) not named: #("Tom" 22 Scheme) #("Sally" 23 C++) records: (define-record person (name age lang)) (define tom ; TYPE: person (make-person "Tom" 22 'Scheme)) (define sally ; TYPE: person (make-person "Sally" 23 'C++)) (person->age sally) ==> 23 (person->name tom) ==> "Tom" (person? sally) ==> #t ------------------------------------------ Q: How would you get the langauge that tom works with? Q: What's this like in C? In Pascal? ------------------------------------------ FOR YOU TO DO Write the procedure average-age: (-> (person person) number) Examples: (average-age tom sally) ==> 22.5 (average-age tom (make-person "baby" 0 'baby-talk)) ==> 11 ------------------------------------------ records can only be declared at the top level Q: how might these be implemented? one way, use vectors to get random access, declare r->f procedures to use vector-ref declare r? to test some part of the record (tag) ------------------------------------------ RECORD DECLARATION SYNTAX ::= (define-record ( {}* ) ) ::= ::= SEMANTICS (define-record auto (name age)) declares the operations: make-auto : (-> (S T) (auto S T)) auto? : (-> (datum) boolean) auto->name : (-> ((auto S T)) S) auto->age : (-> ((auto S T)) T) i.e., you can write: (define mycar ;; TYPE: (auto symbol number) (make-auto 'honda 7)) (auto? mycar) (auto->name mycar) (auto->age mycar) ------------------------------------------ give the types of the expressions ** variant records ------------------------------------------ VARIANT RECORDS def: a *union type* is a type that contains values of ______________ different types. def: a *variant record type* is a type that is a union type, in which the contained types are all _________________. ------------------------------------------ ... two or more e.g., number, datum are both union types ... record types. Q: What's this like in C? In Pascal? Ada? union, variant record Common source of insecurity: using variant records as if they were objects of one type, when really another But in Ada have disjoint union: can always tell what part a value is from (even if the types are the same, as in enumeration) In Scheme, unions, and variant records aren't declared, so can be used insecurely. datum is union of all other types, number is union of integer and real... advantage: convenience We'll often use variant records to represent parse trees... ------------------------------------------ VARIANT RECORDS FOR MODELING GRAMMARS a. Use records for each "interesting" production Example: ::= (lambda () ) | ( ) | (define-record lambda (formal body)) b. Change the types of the operations ------------------------------------------ Point out possible confusion with lambda and the keyword lambda; here this is the symbol lambda (it's not evaluated) Unfortunate, but it's done that way in the book... Book uses: ... (define-record app (rator rand)) (define-record varref (var)) The types are changed using the following .def file ------------------------------------------ A .DEF FILE FOR THIS GRAMMAR ;;; In the file record-lambda-1-exp.def (defrep lambda-1-exp datum) (deftype lambda? (-> (lambda-1-exp) boolean)) (deftype make-lambda (-> (symbol lambda-1-exp) lambda-1-exp)) (deftype lambda->formal (-> (lambda-1-exp) symbol)) (deftype lambda->body (-> (lambda-1-exp) lambda-1-exp)) (deftype varref? (-> (lambda-1-exp) boolean)) (deftype make-varref (-> (symbol) lambda-1-exp)) (deftype varref->var (-> (lambda-1-exp) symbol)) (deftype app? (-> (lambda-1-exp) boolean)) (deftype make-app (-> (lambda-1-exp lambda-1-exp) lambda-1-exp)) (deftype app->rator (-> (lambda-1-exp) lambda-1-exp)) (deftype app->rand (-> (lambda-1-exp) lambda-1-exp)) ------------------------------------------ We'll also add... (deftype lambda-1-exp? (-> (datum) boolean)) (deftype parse-lambda-1-exp (-> (datum) lambda-1-exp)) (deftype unparse-lambda-1-exp (-> (lambda-1-exp) datum))