DOC PREVIEW
UW CSE 341 - Lecture 16 Summary

This preview shows page 1-2 out of 5 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 5 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 5 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 5 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

CSE 341, Spring 2011, Lecture 16 SummaryStandard Disclaimer: These comments may prove useful, but certainly are not a complete summary of allthe important stuff we did in class. They may make little sense if you missed class, but hopefully will helpyou organize and process what you have learned.This lecture covers three topics that are all directly relevant to homework 5:• DrScheme’s define-struct for defining new (dynamic) types in Scheme — and contrasting that withmanually tagged lists• Writing interpreters to implement programming languages — and its relation to “steps” we are skipping(like parsing)• Implementing higher-order functions — the role of environments and closuresdefine-struct and related idioms:In ML, we studied one-of types (in the form of datatype bindings) almost from the beginning, since theywere essential for defining many kinds of data. Scheme’s dynamic typing makes the issue less central sincewe can simply use pairs (or more generally lists) to build anything we want. However, the concept of one-oftypes is still prevalent. Moreover, DrScheme extends the standard Scheme language with something verysimilar to ML’s constructors — a special form called define-struct — and it is instructive to contrast thetwo language’s approaches.Before seeing define-struct, let’s consider “Pure Scheme.” There is no type system to restrict whatwe pass to a function, put in a pair, etc. However, there are different kinds of values — numbers, proce-dures, pairs, strings, symbols, booleans, the empty-list — and built-in predicates like number? and null?to determine what kind of value some particular value is. For values that have “parts” (cons cells), thereare built-in functions for getting the parts (car and cdr). So in a real sense, all Scheme values are in “onebig datatype” and primitives like + check the “tags” of their arguments (e.g., is it a number using number?)and raise an exception for a “run-time type error” before performing some computing (e.g., addition) andmaking a new “tagged” value (e.g., a new number). These “tags” are like ML constructors, but it’s like ourwhole language has just one datatype and everything is in it.Given Pure Scheme, we can still “code up” our own datatypes as an idiom. One common approach isto use lists where the first list element is a symbol to indicate which variant of a one-of type you have. Forexample, consider this ML datatype:datatype exp = Const of int | Add of exp * exp | Negate of expWe could decide to represent similar values in Scheme by using lists where the first element is ’Const, ’Add,or ’Negate. If it is ’Const we would have one more list element which is a number. If it is ’Add we wouldhave two more list elements which are expressions. Notice Scheme’s dynamic typing (specifically lists withelements of different types) is essential. So we could build an expression like this:(list ’Negate (list ’Add (list ’Const 2) (list ’Const 2)))And then functions processing expressions could check the car of the list to see what sort of expression theyhave.However, it is bad style to assume this sort of data representation all over a large program. Instead,we should abstract our decisions into helper functions and then use this interface throughout our program.While the entire notion of an exp datatype is just “in our head” (Scheme has no way for us to specify itexcept in comments), we still know what we need, namely:• A way to build each kind of expression (constructors)• A way to test for the different possibilities (predicates)1• A way to extract the different pieces of each kind of expressionTo keep things simple, we won’t have the extractors raise errors for the wrong kind of thing, though arguablywe should. Defining all the helper functions is easy:(define (Const i) (list ’Const i))(define (Add e1 e2) (list ’Add e1 e2))(define (Negate e) (list ’Negate e))(define (Const? x) (eq? (car x) ’Const))(define (Add? x) (eq? (car x) ’Add))(define (Negate? x) (eq? (car x) ’Negate))(define Const-int cadr)(define Add-e1 cadr)(define Add-e2 caddr)(define Negate-e cadr)Now we can write expressions in a much better, more abstract style:(Negate (Add (Const 2) (Const 2)))Here is an interpreter for our little expression language, using the interface we defined:(define (eval-exp e)(cond [(Const? e) e][(Add? e) (let ([v1 (Const-int (eval-exp (Add-e1 e)))][v2 (Const-int (eval-exp (Add-e2 e)))])(Const (+ v1 v2)))][(Negate? e) (Const (- 0 (Const-int (eval-exp (Negate-e e)))))][#t (error "eval-exp expected an exp")]))As we’ll discuss more below, our interpreter takes an expression (in this case for arithmetic) and produces avalue (an expression that cannot be evaluated more; in this case a constant).While this sort of interface is good style in Pure Scheme, it still requires us to remember to use it and“not cheat”. Nothing is to prevent a bad programmer from writing (list ’Add #f), which will lead toa strange error if passed to eval-exp. Conversely, while we think of (Add (Const 2) (Const 2)) as anexpression in our little language, it actually gets evaluated to a list and there is nothing to keep some otherpart of our program from taking the result of evaluating (Add (Const 2) (Const 2)) and using set-car!to mess it up.define-struct, along with DrScheme’s module system (see lecture 19), fixes these abstraction problems.define-struct is also much more concise than all the helper functions we wrote above. To use it, just writesomething like:(define-struct card (suit value))This defines a new “struct” called card that is like an ML constructor. It adds to the environment aconstructor, a predicate, selectors for the fields, and mutators for the fields. The names of all these bindingsare formed systematically from the constructor name card as followed:• make-card is a function that takes two arguments and returns a value that is a card with suit fieldholding the first argument and value field holding the second argument.• card? is a function that takes one argument and returns #t for values created by calling make-cardand #f for everything else.2• card-suit is a function that takes a card and returns the contents of the suit field. It raises an errorif passed a non-card.• card-value is similar to card-suit for the value field.• set-card-suit! and set-card-value! take a card and mutate the appropriate field.Here is a different


View Full Document

UW CSE 341 - Lecture 16 Summary

Documents in this Course
Macros

Macros

6 pages

Macros

Macros

6 pages

Macros

Macros

3 pages

Mutation

Mutation

10 pages

Macros

Macros

17 pages

Racket

Racket

25 pages

Scheme

Scheme

9 pages

Macros

Macros

6 pages

Load more
Download Lecture 16 Summary
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture 16 Summary and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture 16 Summary 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?