Laney College - Department of Computer Information Systems CIS-061 Lecture Text Doug Dison =========================================================================== LEC-07 OverView =========================================================================== PA-06 SOLUTIONS Controlling Complexity Lecture [Unit 12] Topic 1 Data Directed Programming Topic 2 Putting Functions Into A Data Directed Table (put x y 'data) Topic 3 Retrieving Functions From A Data Directed Table (get x y) Topic 4 Invoking Functions Retrieved From A Data Directed Table Topic 5 Message Passing Variable State Lecture [Unit 15] Topic 1 The Substitution Model Revisited Topic 2 Variable State (set! variable value) Topic 3 Improving The Withdrawal Processor Topic 4 Message Passing Revisited Topic 5 The Functional Paradigm Revisited [TO BE CONTINUED] =========================================================================== PA-06 SOLUTIONS =========================================================================== [Psych!] =========================================================================== Controlling Complexity Lecture [Unit 12] =========================================================================== Table Of Contents Topic 1 Data Directed Programming Topic 2 Putting Functions Into A Data Directed Table Topic 3 Retrieving Functions From A Data Directed Table Topic 4 Invoking Functions Retrieved From A Data Directed Table Topic 5 Message Passing Data Directed Programming While the manifest typing system introduced in the previous unit provides a strategy for implementing generic operations across data types, it also comes saddled with baggage that makes the entire system much more complex. Name mangling across type specific operators. The proliferation of global symbols. The inability to introduce new data types transparently. The question we want to address here is how to get a handle on this complexity. One approach is to store information about each specialized function (its data type and the operation it performs) as data in a table, rather than as code in a function; a technique known as Data Directed Programming. Listing 1 Square Circle Rectangle Area area-square area-circle area-rectangle Perimeter perimeter-square perimeter-circle perimeter-rectangle x> Square Circle Rectangle Y V Area area-square area-circle area-rectangle Perim perimeter-square perimeter-circle perimeter-rectangle Color color-square color-circle color-rectangle CLUE Q1: (define (make-square color side) (list 'square color side)) (define (color-square square) (cadr square)) (define sq1 (make-square 'blue 4) ) (put 'color 'square color-square) (operate 'color sq1) As illustrated in listing 1, each row of a data directed table represents a generic operation, each column a particular abstract type. At the intersection of any particular row / column you will find the type specific function responsible for performing the generic operation on objects of the corresponding type. For instance, to compute the area of a circle, we would supply a lookup function with a pair of keys, area and circle representing the name of the operation and the data type on which the operation is to be performed. The lookup function would search the table, returning the area-circle function bound to that pair of keys, which could then be applied to an entity created with the make-circle constructor. The primary benefit of such an approach is that the operations and data types supported are all chosen by the applications programmer, meaning that the applications programmer can extend the table to include operations (rows) or data types (columns) not originally envisioned by the library programmer without modifying the library. For instance, to add a new shape to the table illustrated in listing 1, all we would have to do would be: Define a function for each operation to be supported for the new data type. Add each function to the table. At the core of this system are 3 tools for inserting, retrieving and applying functions from the database; get, put and operate. Putting Functions Into A Data Directed Table The Scheme library includes a function named put, that puts functions and their identifiers in an initially empty lookup table. Items are placed in the table by invoking the put function with 3 parameters: (put operation datatype function) Q: (put datatype operation function) Y/N ? - YES, as long as your selectors MATCH. A name for the operation that will be used to lookup the function. A name for the data type that will be used to lookup the function. The function itself. Observe how a given sequence of put statements would affect the lookup table. (In this implementation, the functions being added to the table represent manifest types. Therefore, I will use the type flag as the lookup key.) Listing 2 (put 'area 'circle area-circle) (put 'area 'square area-square) (put 'perimeter 'rectangle perim-rectangle) Square Circle Rectangle Area area-square area-circle Perimeter perimeter-rectangle As illustrated in listing 2, each put statement has the effect of placing the designated function at the intersection of its lookup keys in the table. Among the details to note: Adding new operations is equivalent to adding new rows to the table. Were we tomorrow to create a new operation, center to compute the midpoint of a given shape, the operation would appear as a new row in the table, for which we would presumably provide implementations on squares, circles and rectangles. Adding new data types is equivalent to adding new columns to the table. Were we tomorrow to create a new data type, figure-8 the data type would appear as a new column in the table, for which we would presumably provide functions computing an area, perimeter and center. Empty cells represent Undefined Operations; the equivalent of a a type mismatch. (In essence, the gaps in the table perform a limited form of type checking.) Exercises 2. To get a sense of the underlying representation of the table, draw a box and pointer diagram reflecting a possible representation of the table illustrated in listing 2. Retrieving Functions From A Data Directed Table The Scheme library includes a function named get, that given a pair of keys, representing the name and data type bound to a function, returns the corresponding function. (get operation datatype ) Listing 3 Expression Outcome (get 'area 'circle) (get 'perimeter 'rectangle) (get 'perimeter 'circle) () As illustrated in listing 3, the get function returns the function corresponding to the pair of lookup keys received in its parameter list. If the table does not contain an entry for the pair of keys received in its argument list, it returns an empty list. Ordinarily, we could simply take the function returned by the get function and apply it directly to an operand, as illustrated by the sequence of statements in listing 4. Listing 4 (define sq (make-square 5)) ; Create an instance of a square. (put 'area 'square area-square) ; Put the type specific function ; in the table. (get 'area 'square) ; Get the function back. ((get 'area 'square) sq) ; Get the function back and apply it. Unfortunately, such an approach will fail in the face of requests for unsupported operator / datatype pairs. For instance, the expression: ((get 'perimeter 'square) sq) would fail, because a function to compute the area of a perimeter was never added to the table. As a result, the get function would return an empty list, which the encompassing expression would attempt to apply as a procedure, causing it to fail. ( ( ) sq ) Even if a perimeter function had been defined, unless it was added to the table with the corresponding set of lookup keys, the aforementioned expression would fail. Invoking Functions Retrieved From A Data Directed Table This is where the third function in the data directed toolkit comes in; operate. Rather than having to validate each function returned by the get function individually, some versions of the Scheme library include a function named operate, whose purpose is to validate the function returned by the get function prior to applying it, as illustrated in listing 5. For those implementations lacking a version of the operate function, an implementation of the function is included below. Listing 5 (define sq (make-square 5)) ; Create an instance of a square. (put 'area 'square area-square) ; Put the type specific function ; in the table. (operate 'area sq) ; Apply the corresponding function to ; sq. (define (operate operator shape) (define function (get operator (adt-type shape)) (if (eq? #f function) (error "Unsupported Operation / Type :" operator (adt-type shape)) (function (adt-data shape)))) CLUE Q1: (define (operate operator shape) (define function (get operator (adt-type shape))) (if (eq? #f function) (display 'Error-Not-Fount-In-Put-Table) (function shape)))) (define (operate operator shape) ( (get operator (car shape)) shape ) ) With these pieces in place, we could revise our system of generic operators as illustrated in listing 6. Listing 6 (define (area shape) (operate 'area shape)) (define (perimeter shape) (operate 'perimeter shape)) The key idea to remember about data driven programming is its use of tables to represent the attributes of a system as data, rather than as code. Such an approach improves the recyclability of your code by allowing it to be applied to types not in existence when the code was originally developed. It can even be used to optimize the performance of your programs, as you will see in subsequent units. Message Passing Unfortuatenly, both manifest type and data driven systems tend to clutter the global environment with functions. Such systems, whose components are distributed across many functions can be difficult to maintain reliably, because changes to one part of the system tend to propagate to other parts of the system. There is, however, an approach that attempts to control the cascading effects of change in complex systems by consolidating information about an abstract data type in a single location, controlled by a single function. The technique, known as Message Passing, is a system for packaging data in which all of the components of an abstract data type, its variables and functions, are bundled together as a unit. Consequently, maintenance of the abstract type can be confined to a single location. Indeed, this is such a powerful idea that it is the foundation for a revolutionary paradigm for controlling system complexity; a paradigm known as Object Oriented Programming. Here is how it works. Ordinarily, when you think of a constructor, you think of a tool for building data objects. A fraction constructor, for instance, builds data representing the value of an individual fraction. The functions that manipulate that data, the selectors used to extract information from a fraction, or the manipulators used to combine fractions are independent from the data itself. Though in a mathematic sense the operators are inseparable from the data they manipulate, in a computational sense, each is a separately defined entity. This loose coupling between the representation of an abstract data type and the functions that manipulate that type contributes to the frequency with which type mismatches occur. However, under message passing, a constructor returns a procedure, containing all of the functionality necessary to implement a given abstraction on a particular instance of data. Variables representing the underlying data elements of the abstraction. Procedures implementing the underlying behavior of the abstraction. As you will see, message passing borrows from several techniques we have witnessed this semester. Listing 7 (define (make-square x) (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) (define (make-rectangle l w) (define (area l w) (* l w)) (define (perimeter l w) (* (+ l w) 2)) dispatch) (define s1 (make-square 5)) (define s2 (make-square 10)) (define r1 (make-rectangle 5 10)) Expression Outcome s1 (s1 'area) 25 (s2 'area) 100 (r1 'perimeter) 30 (r1 'center) Operator Not Supported: Center Listing 7 illustrates the definition of 2 shape constructors; one for building instances of squares, the other for building instances of rectangles. Both constructors implement a message passing style of programming. Under message passing, the constructor is a function containing the following components: Arguments representing individual attributes of the object being created. Thus, in listing 7, s1 is a square of length 5, while s2 is square of length 10. Locally defined procedures, associated with the abstract data type, accessible only within the confines of the item being constructed. Thus, in listing 7, the make-rectangle constructor contains locally defined functions for computing the area and perimeter of a rectangle; functions accessible only to objects created by this constructor. A function dispenser, known as a dispatch function; a function that invokes the locally defined procedure associated with a keyword received in its parameter list. As illustrated by the outcome of the expression s1, a constructor implemented using message passing style returns a dispatch function, for the purpose of manipulating the arguments instantiated by the constructor when that particular object was created. Thus, when we ask for the area of the square s1 the outcome is 25, because s1 represents a particular square, whose length of 5 was specified when that object was created. In contrast, when we ask for the area of the square s2 the outcome is 100, because s2 represents a different square whose length of 10 was specified when it was created. In essense, what we have done here is package the whole abstraction within a single procedure, eliminating the possibility of type mismatches at the applications level. Once the object is properly constructed, applications cannot mismatch the data with its procedures because they are tightly coupled. Cool huh? There are 2 important advantages to this technique. It Simplifies Maintenance By encapsulating the entire abstraction within a single function we simplify maintenance, reducing the probability that we will omit important changes to randomly scattered components when updating the abstraction. It Enforces Black Box Design Principles By encapsulating the entire abstraction within a function we conceal the implementation of the object from the applications programmer. No matter what the applications programmer tries, he cannot access the variables or functions concealed within the object. All he can do is pass messages to the object, requesting that it perform an operation on itself. By coupling functions and data tightly, the library programmer can eliminate many type mismatches common to the use of abstract data types. Of course, this is not to suggest that there are no disadvantages to the use of message passing. Like manifest types but unlike data directed programming, message passing does not permit the consumer of an abstract data type to extend the operations supported by the type. New data types can be created, but existing types cannot be made to support new operations without creating wrapper types like those described in the previous unit. As you will see when we begin to explore object oriented programming, it can be difficult to design a friendly, consistent user interface using message passing. In the implementation illustrated in listing 6, this problem does not arise, because the internal functions that make up the object are completely self-contained. By this I mean that all of the information these functions need to execute is contained within the object itself, therefore the user interface can be kept simple. However, as you will see in the next unit, when the local functions that comprise an object require information not encapsulated within the object itself (in other words, when an object interacts with the world around it) the interface to the object becomes more complex. With these pieces in place, we could now revise our system of generic operators as illustrated in listing 8. Listing 8 (define (area shape) (shape 'area)) (define (perimeter shape) (shape 'perimeter)) =========================================================================== Variable State Lecture [Unit 15] =========================================================================== Table Of Contents Topic 1 The Substitution Model Revisited Topic 2 Variable State Topic 3 Improving The Withdrawal Processor Topic 4 Message Passing Revisited Topic 5 The Functional Paradigm Revisited Topic 6 The Scheme / OOP Connection [TO BE CONTINUED] The Substitution Model Revisited The idea that a symbol is bound to the value it represents has taken us a long way toward understanding how computers evaluate expressions containing symbolic references. Unfortunately, there are problems for which this computational model is not practical; problems in which the state of the abstraction bound to a symbol changes over time. Consider one such example from the text. Exercises 1. Define a function withdraw that given an amount to be withdrawn from a bank account (represented by an externally defined balance) returns the balance remaining on the account after the transaction has been completed. (Have the function report an error if an attempt is made to withdraw more funds than are contained within the account). Listing 1 illustrates one attempt to solve the problem. Listing 1 (define balance 100) ; My life savings. (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (- balance amount))) Expression Outcome (withdraw 10) 90 (withdraw 20) 80 (withdraw 200) Error: Yeah Right balance 100 Unfortunately, the operation of the withdrawal processor illustrated in listing 1 would not satisfy a bank examiner conducting an audit. The problem is that the withdraw function does not actually alter the state of the balance once the transaction has been completed, it merely computes the difference between the balance (a fixed amount) and the amount being withdrawn in any given transaction. As a result, the account holder may withdraw unlimited funds from the account, as long as she does so in increments less than or equal to the account balance. (Now that's my kind of bank!) Nor would it help to redefine the balance within the body of the withraw function, because both let and define are constructors; they create new instances of symbols within their defining environments (in this case the function's local environment). Such definitions would be confined in scope to the body of their defining function, having no impact on the original symbol from which they were derived in the global environment. When the function terminated, the symbol would disappear. What if we were to redefine the balance with each invocation of the withdraw function, as illustrated in listing 2? Listing 2 Expression Outcome (define balance 100) balance (define balance (withdraw 50)) balance (define balance (withdraw 20)) balance balance 30 While this strategy would satisfy a bank examiner, there are several arguments against it. Such a strategy would only work as long as the withdraw function returned the revised account balance. Were the function to return a different value, such as the amount withdrawn, the strategy would fail. It places responsibility for maintaining the balance on the applications programmer, rather than on the library function, where it belongs. Listing 3 Expression Outcome (define balance 100) balance (define balance (withdraw 20)) balance (withdraw 30) 50 (withdraw 20) 60 balance 80 As illustrated in listing 3, if the applications programmer forgets to redefine the symbol in its original environment in the act of invoking the withdrawal processor, the system will fail. (Really officer, it was a mistake. I just forgot to redefine the balance those 45 times I withdrew money from the account. Purely unintentional.) Needless to say, this is like putting all of the bank's customers on the honor system; too risky strategy to employ. Redefining a symbol is not the same thing as changing a symbol. When you redefine a symbol, you create a new instance of the symbol in the defining environment. When you change a symbol, you change the value bound to the existing symbol. Statements of the form: (define x (+ x 1)) in which the value of a newly defined symbol is derived from the value of an existing symbol whose name it shares are misleading, because people mistakenly infer that such statements change the value of the original symbol, when in fact such statements create a new instance of a symbol; one that masks the existence of its namesake until the redefined symbol goes out of scope. Imagine an implementation of Scheme, in which a symbol could not be redefined in its original environment. Such an interpreter would prohibit statements of the form illustrated in listings 2 and 3. Using such an interpreter, the shortcomings of the substitution model would be apparent; there would be no way to change the account balance. The fact that we can redefine a symbol in its own environment, giving the appearance of having changed the value of the symbol, enables creative ways to work around certain problems, that unfortunately, give a false impression about the behavior of the interpreter. Had Abelson & Sussman simply prohibited the redefinition of any symbol within its defining environment, there would be no confusion over this issue. Isn't the distinction between changing and redefining a symbol merely a distinction without a difference? No. As you will see when we discuss the idea of shared data, there are practical consequences associated with the difference between changing and redefining a variable. What distinguishes this application from its predecessors is that, until now, the name of a symbol has been a fixed representation of a value; a constant. But a balance changes over time. Its value is not fixed, something for which the substitution model, in which a symbol is bound to a value, cannot account. If, the value of a symbol is fixed in time under the substitution model, then it would appear that we need a new paradigm for modeling symbols whose values change over time. Enter variable state. Variable State The term variable state refers to the value of a symbol at a particular point in time. Think of the state of a variable as a picture; a snapshot of the variable in time. The notion of time is important when discussing the state of a variable, because it implies that at some point in time, the state of a variable may differ from its current state; an idea not supported under the substitution model, in which a symbol is bound to a particular value. The simple fact is that prior to the introduction of object oriented programming, none of the tools we have introduced in this course had the capacity to alter the state of a symbol. Not define (which is a constructor), not manipulators (which compute values), not even append (which builds a new list, it does not alter an existing list, as illustrated in listing 4). Listing 4 (define (append lst item) ; This procedure does not append an (if (empty? lst ; item onto a list. It creates a new (cons item '()) ; list containing the values in the ; original list, plus the new item. ; The same can be said for all of the ; constructors we have devised this ; semester. (cons (car lst) (append (cdr lst) item)))) Expression Outcome (define lst (list 1 2 3)) lst lst (1 2 3) (append lst 4) (1 2 3 4) lst (1 2 3) Enter Set! Listing 5 (define balance 100) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) Expression Outcome (withdraw 10) 90 (withdraw 20) 70 (withdraw 50) 20 balance 20 Set! is Scheme's equivalent of the assigment operator. In most programming languages, we use expressions of the form a = b to alter the state of an existing variable. (In some languages, statements of this form also serve as constructors for as yet undefined symbols.) In Scheme, we use the special form (set! a b) to alter the state of an existing variable. This is what distinguishes set! from define. When you define a symbol, you create a new representation of the symbol, even if a symbol bearing that name already exists. When you use set!, you alter the value of a previously defined symbol. Note that the value returned by set! is undefined. This means that in order to return a meaningful value, functions that employ set! must do 2 things at once: Alter the value of an existing variable. Return a meaningful value in a separate expression. One way to do this is through the use of a special form known as a sequence, represented in most implementations of Scheme as begin. A sequence is a set of expressions, that execute sequentially, returning the outcome of the final expression in the sequence. There is a reason that we need to introduce begin at the same time we introduce set! Under the functional paradigm, expressions don't do anything except compute (represent) a value. Since a function can only return 1 value, it made no sense to include more than 1 expression within the body of a function. But when we invoke set! there is an effect that lasts beyond the computation of the expression, therefore it makes sense to have other expressions that follow (and presumably benefit from) the effect. Exercises 2. Earlier, I said that set! was a special form. Explain why set! must be implemented as a special form. 3. Do you see any potential danger in the use of set!? If so, explain. Improving The Withdrawal Processor While the version of the withdrawal processor illustrated in listing 5 solves the immediate problem of maintaining an accurate account balance, the design could be improved. The biggest problem with the design is that the variable representing the account balance is bound to the global environment, making it accessible, and therefore, mutable to any function within the program. (One consequence of introducing set! is that it gives any function the ability to alter the value of any symbol defined in any of that function's defining environments, all the way back to the global environment; a powerful, some would suggest, frightening prospect.) At first glance, you might think that this problem could be solved by hiding the balance within the withdrawal processor itself. Unfortunately, such a strategy would not work, because local symbols are created and destroyed each time their defining function is invoked. What we need is a way to hide a symbol within a local environment, yet have the value of that symbol persist from one invocation of the function to the next; in a manner similar to that used to preserve local state in a previous unit; by encapsulating the local state of the withdrawal processor in a persistant environment. Listing 6 (define (make-withdrawal balance) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) withdraw) (define my-withdraw (make-withdrawal 100)) (define your-withdraw (make-withdrawal 500)) Expression Outcome (my-withdraw 10) 90 (your-withdraw 20) 480 (my-withdraw 30) 60 (your-withdraw 100) 380 Listing 6 illustrates how a function can maintain its own local state variable, as a let, a local definition or a parameter. The basic idea is to encapsulate the function within a larger environment that contains its own state variable. As with message passing, the defining environment goes anywhere the function goes, allowing the function to read or alter the state of the variable whenever the function is invoked. Bascially, you can think of the make-withdrawal function as a constructor that returns a function, each instance of which has access to its own private, persistant balance. (Note how each account has its own balance.) Some of you may be wondering how such an implementation is possible, given the temporal nature of local environments. The answer, of course is that such behavior cannot be accounted for under the current model. We will have to revisit this model (in subsequent units) if we are to account for the changes in behavior outlined in this unit. Message Passing Revisited Those of you who tried exercise 4, probably noticed that the deposit and withdrawal processors maintain separate balances. The problem, of course, is that deposits and withdrawals need to share access to the same balance if they are to effectively model the behavior of a bank account. Some might consider it ironic that all semester I have been warning you about the vulnerability of programs that share data. Now, I am urging you to share data. What do I want; the reliability that comes with concealing data or the power that comes with sharing data. The answer, of course, is both. One strategy of achieving both is to use the message passing techniques illustrated in a previous unit to create an account constructor; a function that contains all of the variables and functions necessary to implement the account abstraction by combining elements of message passing and variable state. Listing 8 (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity) (cond ((equal? activity 'deposit) deposit) ((equal? activity 'withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) Expression Outcome (define my-account (make-account 100)) my-account (define your-account (make-account 500)) your-account ((my-account 'deposit) 50) 150 ((your-account 'withdraw) 100) 400 ((my-account 'withdraw) 100) 50 ((your-account 'deposit) 10) 410 ((my-account 'borrow) 100) Error: Unsupported Activity: Borrow What we have created here is an object; a self-contained implementation of an abstract idea consisting of local state variables and the methods that manipulate them. Believe it or not, this simple technique provides the foundation for the programming paradigm known as Object Oriented Programming. The Functional Paradigm Revisited By this juncture you are probably wondering about a curious aspect of the Scheme language. One of the first things we learned this semester was how to define a symbol to represent a value. Here we are weeks into the semester and we have only now introduced the notion of how to change the value of a symbol; among the most common operations in any language, and one of the first techniques taught in virtually every introductory programming course! Why have we waited so long to introduce what is one of the most common techniques in programming? One of the central themes of this course is that there are different models of programming of which programmers should be aware. By models of programming I mean approaches toward programming, ideas about ways to analyze and solve problems. Until now, the model on which we have relied exclusively has been known as Functional Programming. Functional programming is a style of programming in which all programs are viewed as functions and symbols as fixed values. In a previous exercise I asked why set! had to be implemented as a special form. To answer this question, think about the substitution model of evaluation, which states that the name of a variable is merely a symbolic representation of its value. Now, if the substitution model applied to set!, how would we evaluate the sequence of expressions illustrated in listing 10? Listing 10 (define a 1) (set! a 2) Using applicative order, we would interpret this expression to mean: (set! 1 2) or Change the value of 1 to 2. Needless to say, this would wreak havoc with the interpreter's ability to do arithmetic. How would the interpreter respond, were we subsequently to evaluate the expression (+ 1 1)? The point is that the substitution model, in which a symbol is merely a name for a value cannot account for things like variable assignment. If we are to have the ability to alter the meaning of a symbol in time, we need a more robust model for thinking about the meaning of a variable. What model might that be? How about one in which the name of a variable represents a location in memory, rather than a fixed value, the contents of which may change over the life of a program. Among the benefits of such a model are: It is more efficient than its functional counterpart. For instance, as you will see later in the semester, it is possible to model the state of a variable over time without resorting to assignment. The solution is less efficient, O( n ) vs. O( 1 ) but no less effective. It can be used to represent both fixed and transient values. Why then have we waited so long to introduce variable state into our programs? Because variable state introduces complications not present under the functional paradigm. For instance, under the functional paradigm, the sequence of operations is implicit in the composition of a function. This is not the case under the imperative paradigm, in which the programmer has more freedom to manipulate the sequence of operations to optimize the performance of the program. Unfortunately, such manipulations can lead to sequencing errors that would be less likely, or in some cases impossible, under the functional paradigm. More importantly, the functional paradigm is more suitable to the design of programming languages for parallel processing environments than its imperative counterparts. Studies have shown that a series of inexpensive microprocessors running in tandem can approximate the performance of single processor super-computers systems costing many times as much to produce. Systems that employ variable state are very difficult to model in parallel processing environments, because of the synchronization problems they introduce. Environments that support variable state are prone to failure if the value of a variable used by one process is altered in the middle of some computation by another asynchronous process sharing access to the same data. Languages that support the functional paradigm are not prone to such errors, because they do not permit the value of a symbol to change. Therefore, as parallel processing and distributed computing systems gain a foothold in the marketplace, the demand for programmers skilled in the functional paradigm is likely to increase. The Scheme / OOP Connection [TO BE CONTINUED .] =========================================================================== ADDENDUM =========================================================================== Welcome to DrScheme, version 101. Language: Graphical Full Scheme (MrEd). > (load"berk2.scm") #t > (define empty-tree '()) (define (empty-tree? tree) (equal? tree empty-tree)) (define (leaf? tree) (and (not (empty-tree? tree)) (empty-tree? (tree-left tree)) (empty-tree? (tree-right tree)))) (define (tree? tree) (list? tree)) (define (make-tree data left right) (list data left right)) (define (make-leaf data) (make-tree data empty-tree empty-tree)) (define tree-data car) (define tree-left cadr) (define tree-right caddr) (define (inorder tree) (if (empty-tree? tree) '() (se (inorder (tree-left tree)) (tree-data tree) (inorder (tree-right tree))))) > (define (is-list-in-order? lst) (cond ((eq? (cdr lst) '()) #t) ((> (car lst) (cadr lst)) #f) (else (is-list-in-order? (cdr lst))))) (define (BST? tree) (is-list-in-order? (inorder tree) ) ) > (define tree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree empty-tree 5) 3) 2) 1) 4) 7) 6) 9) 8)) reference to undefined identifier: append-bstree > (define (append-bstree tree item) (cond ((empty-tree? tree) (make-leaf item)) ((< item (tree-data tree)) (make-tree (tree-data tree) (append-bstree (tree-left tree) item) (tree-right tree))) (else (make-tree (tree-data tree) (tree-left tree) (append-bstree (tree-right tree) item))))) > (define tree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree (append-bstree empty-tree 5) 3) 2) 1) 4) 7) 6) 9) 8)) > tree (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) > (BST? tree) #t > (define tree2 '(2 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) ) > tree2 (2 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) > (BST? tree2) #f > (load"trace.ss") > (trace append-bstree) (append-bstree) > (append-bstree tree 6.5) |(append-bstree (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) 6.5) | (append-bstree (7 (6 () ()) (9 (8 () ()) ())) 6.5) | |(append-bstree (6 () ()) 6.5) | | (append-bstree () 6.5) | | (6.5 () ()) | |(6 () (6.5 () ())) | (7 (6 () (6.5 () ())) (9 (8 () ()) ())) |(5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () (6.5 () ())) (9 (8 () ()) ()))) (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () (6.5 () ())) (9 (8 () ()) ()))) > (define tree3 (append-bstree tree 6.5) ) |(append-bstree (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) 6.5) | (append-bstree (7 (6 () ()) (9 (8 () ()) ())) 6.5) | |(append-bstree (6 () ()) 6.5) | | (append-bstree () 6.5) | | (6.5 () ()) | |(6 () (6.5 () ())) | (7 (6 () (6.5 () ())) (9 (8 () ()) ())) |(5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () (6.5 () ())) (9 (8 () ()) ()))) > (BST? tree3) #t > (cons 5 '(firstn lastn)) (5 firstn lastn) > (define make-rec cons) > (define rec1 (make-rec 4 '(Sallie Mae))) > rec1 (4 sallie mae) > (define rec2 (make-rec 6 '(Freddie Mac))) > rec2 (6 freddie mac) > (< rec1 rec2) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: <: expects type as 2nd argument, given: (6 freddie mac); other arguments were: (4 sallie mae) > (< (car rec1) (car rec2)) #t > (define rec-key car) > (define rec-data cdr) > (if (record rec1) 1 0 ) reference to undefined identifier: record > (if rec1 0 1) 0 > (if rec2 1 0) 1 > (if #t 1 0) 1 > (if #f 1 0) 0 > (if '() 1 0) 1 > (if rec1 1 0) 1 > (if '(this is a list) 1 0) 1 > (if 'atom 1 0) 1 > (if 0 1 0) 1 > (if '(a.b) 1 0) 1 > (define make-branches list) (define first-branch car) (define remaining-branches cdr) (define empty-branches '()) (define (empty-branches? branches) (equal? branches empty-branches)) (define make-gtree cons) (define gdata car) (define gbranches cdr) (define empty-gtree '()) (define (empty-gtree? tree) (equal? tree empty-gtree)) (define (make-gleaf data) (make-gtree data empty-branches)) (define (gleaf? tree) (empty-branches? (gbranches tree))) > (define CS61A-1 (make-gleaf 'Budgor)) (define CS61A-2 (make-gleaf 'Clancy)) (define CS61A-3 (make-gleaf 'Harvey)) (define CS61B-1 (make-gleaf 'Clancy)) (define CS61C-1 (make-gleaf 'Fateman)) (define CS61C-2 (make-gleaf 'Yellick)) (define CS61A (make-gtree 'CS61A (make-branches CS61A-1 CS61A-2 CS61A-3))) (define CS61B (make-gtree 'CS61B (make-branches CS61B-1))) (define CS61C (make-gtree 'CS61C (make-branches CS61C-1 CS61C-2))) (define CS (make-gtree 'CS (make-branches CS61A CS61B CS61C))) (define PS1-1 (make-gleaf 'Polsby)) (define PS1-2 (make-gleaf 'Wolfinger)) (define PS2-1 (make-gleaf 'Cain)) (define PS1 (make-gtree 'PS1 (make-branches PS1-1 PS1-2))) (define PS2 (make-gtree 'PS2 (make-branches PS2-1))) (define PS (make-gtree 'PS (make-branches PS1 PS2))) (define PH1 (make-gleaf 'Searle)) (define PH (make-gtree 'PH (make-branches PH1))) (define UCB (make-gtree 'Berkeley (make-branches CS PS PH))) > ucb (berkeley (cs (cs61a (budgor) (clancy) (harvey)) (cs61b (clancy)) (cs61c (fateman) (yellick))) (ps (ps1 (polsby) (wolfinger)) (ps2 (cain))) (ph (searle))) > (define (max-siblings tree) (define max1 0) (define (max-branches branches) (if (empty-branches? branches) 0 (max (count branches) (max-siblings (first-branch branches)) (max-branches (remaining-branches branches))))) (if (empty-gtree? tree) 0 (max (max-branches (gbranches tree))))) > (max-siblings ucb) 3 > (trace max-siblings) (max-siblings) > (max-siblings ucb) |(max-siblings (berkeley (cs (cs61a (budgor) (clancy) (harvey)) (cs61b (clancy)) (cs61c (fateman) (yellick))) (ps (ps1 (polsby) (wolfinger)) (ps2 (cain))) (ph (searle)))) | (max-siblings (cs (cs61a (budgor) (clancy) (harvey)) (cs61b (clancy)) (cs61c (fateman) (yellick)))) | |(max-siblings (cs61a (budgor) (clancy) (harvey))) | | (max-siblings (budgor)) | | 0 | | (max-siblings (clancy)) | | 0 | | (max-siblings (harvey)) | | 0 | |3 | |(max-siblings (cs61b (clancy))) | | (max-siblings (clancy)) | | 0 | |1 | |(max-siblings (cs61c (fateman) (yellick))) | | (max-siblings (fateman)) | | 0 | | (max-siblings (yellick)) | | 0 | |2 | 3 | (max-siblings (ps (ps1 (polsby) (wolfinger)) (ps2 (cain)))) | |(max-siblings (ps1 (polsby) (wolfinger))) | | (max-siblings (polsby)) | | 0 | | (max-siblings (wolfinger)) | | 0 | |2 | |(max-siblings (ps2 (cain))) | | (max-siblings (cain)) | | 0 | |1 | 2 | (max-siblings (ph (searle))) | |(max-siblings (searle)) | |0 | 1 |3 3 > (max 3 4 5) 5 > (max '(3 4 5)) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: max: expects argument of type ; given (3 4 5) > (define (max-siblings tree) (define (max-branches branches) (if (empty-branches? branches) 0 (max (count branches) (max-siblings (first-branch branches)) (max-branches (remaining-branches branches))))) (if (empty-gtree? tree) 0 (max (max-branches (gbranches tree))))) > (max-siblings tree) 2 > tree (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) > max1 reference to undefined identifier: max1 > (define (atom? x) (and (not (null? x)) (not (pair? x)))) (define (toi lst) (cond ((null? lst) '() ) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst) ) ((null? (cddr lst)) (cadr lst)) (else (append (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))) > (define exp (make-gtree '+ (make-branches (make-gtree '* (make-branches (make-gtree 2 (make-branches)) (make-gtree 3 (make-branches)) (make-gtree 4 (make-branches)))) (make-gtree 5 (make-branches)) (make-gtree 6 (make-branches))))) > exp (+ (* (2) (3) (4)) (5) (6)) > (toi exp) append: expects argument of type ; given * > (define (toi lst) (cond ((null? lst) '() ) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst) ) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))) > (toi exp) ((2 * (3 * (4))) + (5 + (6))) > (put 1 2 'blue) ok > (get 1 2) blue > (get 4 5) #f > (put 2 2 +) ok > (get 2 2) # > (put 0 0 4) ok > (get 0 0) 4 > (put -4 -3 'sampson) ok > (get -4 -3) sampson > (put 'word1 'word2 9) ok > (get 'word1 'word2) 9 > (put 1 2 3 4) procedure put: expects 3 arguments, given 4: 1 2 3 4 > (put 1 2 '(4 5 6) ) ok > (put '(3 4 5) '(3 4) 55) ok > (get '(3 4 5) '(3 4) ) 55 > (put 1 1 (define (toi lst) (cond ((null? lst) '() ) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst) ) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))) ) Invalid position for internal definition > (put 1 1 '(define (toi lst) (cond ((null? lst) '() ) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst) ) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))) ) ok > (get 1 1) (define (toi lst) (cond ((null? lst) '()) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst)) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))) > ((get 1 1) tree) procedure application: expected procedure, given: (define (toi lst) (cond ((null? lst) '()) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst)) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))); arguments were: (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) > ( (eval (get 1 1)) tree) procedure application: expected procedure, given: #; arguments were: (5 (3 (2 (1 () ()) ()) (4 () ())) (7 (6 () ()) (9 (8 () ()) ()))) > ( (eval (get 1 1)) exp) procedure application: expected procedure, given: #; arguments were: (+ (* (2) (3) (4)) (5) (6)) > ( (get 1 1) exp) procedure application: expected procedure, given: (define (toi lst) (cond ((null? lst) '()) ((atom? (car lst)) (cond ((null? (cdr lst)) (car lst)) ((null? (cddr lst)) (cadr lst)) (else (list (toi (cadr lst)) (car lst) (toi (cons (car lst) (cddr lst))))))) ((list? (car lst)) (car lst)))); arguments were: (+ (* (2) (3) (4)) (5) (6)) > (define word '(+ 2 3)) > word (+ 2 3) > (eval word) 5 > (put 'area 'circle area-circle) (put 'area 'square area-square) (put 'perimeter 'rectangle perim-rectangle) reference to undefined identifier: area-circle > (put 'area 'circle area-circle) (put 'area 'square area-square) (put 'perimeter 'rectangle perim-rectangle) reference to undefined identifier: area-circle > (put 'area 'square area-square) reference to undefined identifier: area-square > (define (area-circle r) (* 3.14 (* r r))) > (put 'area 'circle area-circle) ok > ((get 'area 'circle) 6) 113.04 > (get 'area 'circle) # > (empty? #f) #f > (eq? #f (get 100 100)) #t > (define (operate operator shape) (define function (get operator (adt-type shape)) (if (eq? #f function) (error "Unsupported Operation / Type :" operator (adt-type shape)) (function (adt-data shape))))) Malformed define > (define (operate operator shape) (define function (get operator (adt-type shape)) (if (eq? #f function) (display 'UnknownFunctionOrData ) (function (adt-data shape))))) Malformed define > (define (operate operator shape) (define function (get operator (adt-type shape))) (if (eq? #f function) (display 'UnknownFunctionOrData ) (function (adt-data shape)))) > (define (make-circle r) (list 'cirle r)) > (define (make-circle r) (list 'circle r)) > (define (adt-type shape) (car shape)) > (define (adt-data shape) (cdr shape)) > (define c1 (make-circle 10)) > c1 (circle 10) > (operate 'area c1) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: *: expects type as 1st argument, given: (10); other arguments were: (10) > (* (10) ) procedure application: expected procedure, given: 10 (no arguments) > (define (area-circle r) (* 3.14 (* (adt-data r) (adt-data r) ))) > (area-circle c1) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: *: expects type as 1st argument, given: (10); other arguments were: (10) > (adt-data c1) (10) > (define (area-circle r) (* 3.14 (* (car (adt-data r)) (car (adt-data r) ))) ) > (adt-data c1) (10) > (area-circle c1) 314.0 > (* (10) (10)) procedure application: expected procedure, given: 10 (no arguments) > (* (car '(10)) (car '(10)) ) 100 > (operate 'area c1) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: *: expects type as 1st argument, given: (10); other arguments were: (10) > (put 'area 'circle area-circle) ok > (operate 'area c1) car: expects argument of type ; given () > c1 (circle 10) > (define (area-circle r) (* 3.14 (* (car (adt-data r)) (car (adt-data r) ))) ) > (adt-data c1) (10) > (car (adt-data c1)) 10 > (define (operate operator shape) (define function (get operator (adt-type shape))) (if (eq? #f function) (display 'UnknownFunctionOrData ) (function (adt-data shape)))) > ((get 'area 'circle) c1) 314.0 > (operate 'area c1) car: expects argument of type ; given () > Welcome to DrScheme, version 101. Language: Graphical Full Scheme (MrEd). > (define (make-circle r) (list 'circle r)) > (define (adt-type shape) (car shape)) > (define (adt-data shape) (cdr shape)) > (define (area-circle r) (* 3.14 (* (car (adt-data r)) (car (adt-data r) ))) ) > (put 'area 'circle area-circle) reference to undefined identifier: put > (load"berk2.scm") #t > (put 'area 'circle area-circle) ok > (get 'area 'circle) # > (define (operate operator shape) (define function (get operator (adt-type shape))) (if (eq? #f function) (display 'UnknownFunctionOrData ) (function (adt-data shape)))) > (define c1 (make-circle 9)) > c1 (circle 9) > (operate 'area c1) car: expects argument of type ; given () > (define (area-circle r) (* 3.14 (* (car r)) (car r) )) > (put 'area 'circle area-circle) ok > (operate 'area c1) 254.34 > ((get 'area 'circle) c1) C:\Reserved\SICP\PLT-101\berk2.scm: 1283.2-1283.33: *: expects argument of type ; given circle > (define (operate operator shape) (define function (get operator (adt-type shape))) (if (eq? #f function) (display 'UnknownFunctionOrData ) (function (adt-data shape)))) > ((get 'area 'circle) (adt-data c1 ) ) 254.34 > (define (my-func x) (define y 4) (define z (* y x)) z) > (my-func 5) 20 > (define y 100) > (my-func 5) 20 > (define x 200) > (my-func 5) 20 > (define (my-func x) (define y 4) (define z (another-func a) (+ a y x) ) z) Malformed define > (define (make-square x) (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) > (define (my-func x) (define y 4) (define (another-func a) (+ a y x) ) z) > (define (my-func x) (define y 4) (define (another-func a) (+ a y x) ) another-func) > (my-func 50) # > + # > (define (yet-another-func x) (+ x x x)) > yet-another-func # > ( (my-func 50) 3) 57 > (define (my-func x) (define y 4) (define (another-func a) (+ a y x b) ) another-func) > (define b 1000) > ( (my-func 50) 3) 1057 > (define temp (my-func 50) ) > temp # > ( temp 3) 1057 > (4 4) procedure application: expected procedure, given: 4; arguments were: 4 > '(4 4) (4 4) > (define (my-func x) (define y 4) (define (another-func a) (+ a y x b) ) another-func) > (define temp2 (my-func 60)) > (temp2 70) 1134 > temp2 # > (tepm2 80) reference to undefined identifier: tepm2 > (temp2 80) 1144 > (define a 5) > (temp2) procedure another-func: expects 1 argument, given 0 > (temp2 80) 1144 > (temp2 a) 1069 > (define (make-square x) (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) > (define s1 (make-square 6)) > s1 # > (s1 'area) 36 > (s1 'perimeter) 24 > s1 # > (define (make-rectangle l w) (define (area l w) (* l w)) (define (perimeter l w) (* (+ l w) 2)) (define (dispatch operator) (cond ((equal? operator 'area) (area l w)) ((equal? operator 'perimeter) (perimeter l w)) (else (error "Operator Not Supported :" operator)))) dispatch) > (define r1 (make-rectangle 2 4)) > r1 # > (define r2 (make-rectangle 4 6)) > r2 # > (r1 'area) 8 > (r2 'area) 24 > (define r1 (make-rectangle 6 8)) > (r1 'area) 48 > (define (make-rectangle l w) (define (area l w) (* l w)) (define (perimeter l w) (* (+ l w) 2)) (define (dispatch operator) (cond ((operator l w)) (else (error "Operator Not Supported :" operator)))) dispatch) > area reference to undefined identifier: area > (define (area x y) (* x y)) > (define (perimeter x y) (+ x x y y)) > (define r3 (make-rectangle 10 12)) > (r3 area) 120 > (r3 perimeter) 44 > (define (my-func x) (define y 4) (define (another-func a) (+ a y x b) ) another-func) > (temp2) procedure another-func: expects 1 argument, given 0 > (define balance 100) ; My life savings. (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (- balance amount))) > balance 100 > (withdraw 10) 90 > (withdraw 120) Yeah Right > balance 100 > (define balance (withdraw 20)) > balance 80 > (withdraw 10) 70 > balance 80 > (define (append lst item) ; This procedure does not append an (if (empty? lst ; item onto a list. It creates a new (cons item '()) ; list containing the values in the ; original list, plus the new item. ; The same can be said for all of the ; constructors we have devised this ; semester. (cons (car lst) (append (cdr lst) item)))) ) Malformed if > (define balance 100) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) > balance 100 > (withdraw 20) 80 > balance 80 > (set! balance 70) > (begin (set! balance 50) balance) 50 > (set! balance 50) > (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (set! balance (- balance amount)) )) > (withdraw 30) > balance 20 > (withdraw 10) > balance 10 > (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) > (define (make-withdrawal balance) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) withdraw) > (define account1 (make-withdrawl 100)) reference to undefined identifier: make-withdrawl > (define account1 (make-withdrawal 100)) > (account1 20) 80 > (define account2 (make-withdrawal 200)) > (account2 50) 150 > (account1 10) 70 > (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity) (cond ((equal? activity 'Deposit) deposit) ((equal? activity 'Withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) > (define my-account (make-account 100)) > (define your-account (make-account 200)) > ((my-account 'deposit) 50) 150 > my-account # > (my-account 'deposit) # > ( (my-account 'deposit) -50) 100 > ( (my-account 'deposit) 0) 100 > Welcome to DrScheme, version 101. Language: Graphical Full Scheme (MrEd). > (define rember (lambda ( a lat ) (cond ( (null? lat) '() ) (else (cond ((eq? (car lat) a) (cdr lat)) (else (rember a (cdr lat)))))))) > (define lat1 '(lettuce and tomato)) > lat1 (lettuce and tomato) > (define a bacon) reference to undefined identifier: bacon > (define a 'bacon) > (rember a lat1) () > (define lat1 '(bacon lettuce and tomato)) > (rember a lat1) (lettuce and tomato) > Reference: [Controllig Complexity Lecture] 1. Suppose that you were developing a graphics library. In addition to determining the area and perimeter of a given shape, you might want to know its foreground color. What would you have to do to introduce such a feature into the table? 3. A figure-8 is a shape formed by joining 2 circles of a designated radius together. Implement a constructor for a figure-8 using the message passing techniques described in listing 7: Listing 7 (define (make-square x) ; Implementation 1 (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) (define (make-rectangle l w) ; Implementation 2 (define (area l w) (* l w)) (define (perimeter l w) (* (+ l w) 2)) (define (dispatch operator) (cond ((equal? operator 'area) (area l w)) ((equal? operator 'perimeter) (perimeter l w)) (else (error "Operator Not Supported :" operator)))) dispatch) (define s1 (make-square 5)) (define s2 (make-square 10)) (define r1 (make-rectangle 5 10)) Expression Outcome s1 (s1 'area) 25 (s2 'area) 100 (r1 'perimeter) 30 (r1 'center) Operator Not Supported: Center [Variable State Lecture] 4. Create a deposit processor modeled on the withdrawal processor illustrated in listing 6: Listing 6 (define (make-withdrawal balance) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) withdraw) (define my-withdraw (make-withdrawal 100)) (define your-withdraw (make-withdrawal 500)) Expression Outcome (my-withdraw 10) 90 (your-withdraw 20) 480 (my-withdraw 30) 60 (your-withdraw 100) 380 FALL 2000 ADDENDUM ------------------ Welcome to DrScheme, version 101. Language: Graphical Full Scheme (MrEd). > (load"berk2.scm") #t > (define (do-math x) (define (cube x) (* x x x)) (cube x)) > (define (square x) (define (cube x) (* x x x)) (* x x)) > (cube x) reference to undefined identifier: cube > (define (cube x) (* x x x)) > (cube 3) 27 > (define (descend branches) (if (empty-branches? branches) 0 (+ (count-leaf-gtree (first-branch branches)) (descend (remaining-branches branches))))) > (define (same? tree key) (cond ((empty-gtree? tree) empty-gtree) ; If the tree is empty, no ; match. ((equal? key (gdata tree)) tree) ; If the key matches, return ; the root. ; Otherwise, check the ; branches. (else (find-branch (gbranches tree) key)))) > (define (count-subtree tree key offset) (define (same? tree key) (cond ((empty-gtree? tree) empty-gtree) ((equal? key (gdata tree)) tree) (else (find-branch (gbranches tree) key)))) ) Internal definition not followed by expression > (define (same? tree key) (cond ((empty-gtree? tree) empty-gtree) ((equal? key (gdata tree)) tree) (else (find-branch (gbranches tree) key))) ) > (define empty-gtree '()) (define (empty-gtree? tree) (equal? tree empty-gtree)) > (define gdata car) (define gbranches cdr) > (define (find-branch branches key) (if (empty-branches? branches) empty-gtree (let ((match (same? (first-branch branches) key))) (if (empty-gtree? match) (find-branch (remaining-branches branches) key) match)))) > (define empty-branches '()) (define (empty-branches? branches) (equal? branches empty-branches)) > (define first-branch car) > (define empty-gtree '()) (define (empty-gtree? tree) (equal? tree empty-gtree)) > (define remaining-branches cdr) > (define tree1 '(a ((b '()) (c '()) (d '())) ) ) > tree1 (a ((b '()) (c '()) (d '()))) > (define tree2 '(a ((b '()) (c '()) (d '())) ) ) > tree2 (a ((b '()) (c '()) (d '()))) > (define tree3 '(a ((e '()) (f '()) (g '())) ) ) > (same? tree1 tree2) () > (same? tree1 tree3) () > (same? tree1 a) reference to undefined identifier: a > (same? tree1 'a) (a ((b '()) (c '()) (d '()))) > (same? tree1 'b) () > (find-branch (gbranches tree1) 'b) () > (gbranches tree1) (((b '()) (c '()) (d '()))) > (define tree1 '(a (b '()) (c '()) (d '()) ) ) > tree1 (a (b '()) (c '()) (d '())) > (gbranches tree1) ((b '()) (c '()) (d '())) > (define list1 '(a b c d)) > (car list1) a > (cdr list1) (b c d) > (define list2 '(a b)) > (car list2) a > (cdr list2) (b) > (define list3 (cons b '() )) reference to undefined identifier: b > (define list3 (cons 'b '() )) > list3 (b) > (define list4 (cons 'a list3)) > list4 (a b) > ;( a . ( b . '() ) ) '() () > (find-branch (gbranches tree1) 'b) (b '()) > (same? tree1 'b) (b '()) > (key branch branch .... ) reference to undefined identifier: key > (cons 'a (list '(b c d))) (a (b c d)) > (cons 'a (list 'b 'c 'd)) (a b c d) > (make-branches CS61A-1 CS61A-2 CS61A-3) reference to undefined identifier: make-branches > (list ca cb cc) reference to undefined identifier: ca > (list 'ca 'cb 'cc) (ca cb cc) > (define tree1 '(a (b '()) (c '()) (d '()) ) ) > (define tree4 '(a (b ) (c ) (d ) ) ) > (define list 5 '(6) ) Malformed define > (define list5 '(6) ) > list5 (6) > (car list5) 6 > (cdr list5) () > (max 4 25 43 6432 432 5 2) 6432 > (max 's 'lsjdf 'we) C:\Reserved2\SICP\PLT-101\berk2.scm: 1283.2-1283.33: max: expects type as 1st argument, given: s; other arguments were: lsjdf we > (more? 'b 'd) reference to undefined identifier: more? > (before? 'b 'g) #t > (before? 'g 'a) #f > (after? 'ldsfkj 'lkf) reference to undefined identifier: after? > (define (after? x y) (and (not (before? x y)) (not (eq? x y)))) > (eq? 'f 'g) #f > (equal? 'f 'g) #f > (before 'This 'this) reference to undefined identifier: before > (before? 'This 'this) #f > (before? 'this 'This) #f > (before? 'para 'paranoia) #t > (before? 'paranoia 'para) #f > (eq? '(a b) '(b c)) #f > (equal? '(a b) '(b c)) #f > (put 1 2 'Joe) ok > (get 1 2) joe > (put 1 1 'Fred) ok > (get 1 1) fred > (get 1 2) joe > (get 2 2) #f > (put 'any 'thing 'more) ok > (get 'any 'thing) more > (put 'yes 'afunc (lambda (x) (* x x)) ) ok > ((get 'yes 'afunc) 5) 25 > the-get/put-table (*table* (yes (afunc . #)) (any (thing . more)) (1 (1 . fred) (2 . joe))) > (define (make-square x) (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) > (define square-side-5 (make-square 5)) > square-side-5 # > + # > (square-side-5 'area) 25 > (eval square-side-5) # > (make-square 5) # > (dispatch 'area) reference to undefined identifier: dispatch > (define (silly) +) > silly # > (silly) # > ((silly) 4 5 6) 15 > (define any (silly)) > (any 5 6 7) 18 > (cond ((equal? operator 'area) (* 5 5)) ((equal? operator 'perimeter) (* 5 4)) (else (error "Operator Not Supported :" operator))) reference to undefined identifier: operator > (define balance 100000) > balance 100000 > (define balance 120000) > balance 120000 > (define (deposit balance value) (+ balance value)) > balance 120000 > (deposit balance 40) 120040 > balance 120000 > (define (deposit balance value) (define balance (+ balance value))) Internal definition not followed by expression > (define (deposit balance value) (define balance (+ balance value)) balance) > balance 120000 > (deposit balance 40) C:\Reserved2\SICP\PLT-101\berk2.scm: 1283.2-1283.33: +: expects type as 1st argument, given: #; other arguments were: 40 > (define (deposit bal value) (define balance (+ bal value)) balance) > balance 120000 > (deposit balance 40) 120040 > balance 120000 > (define (deposit bal value) (set! balance (+ bal value)) balance) > balance 120000 > (deposit balance 40) 120040 > balance 120040 > (define (deposit bal value) (define balance (deposit bal 40)) balance) > (deposit balance 40) user break > (define list1 '(1 2 3)) > list1 (1 2 3) > (append 0 list1) append: expects argument of type ; given 0 > (append list1 0) (1 2 3 . 0) > list # > list1 (1 2 3) > (define (withdraw amount) (define balance 100) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) > balance 120040 > (withdraw 40) 60 > balance 120040 > (define (make-withdrawal balance) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) withdraw) > (define joes-account (make-withdrawal 100)) > (define marys-account (make-withdrawal 200)) > joes-account # > marys-account # > (joes-account 20) 80 > (marys-account 10) 190 > (joes-account 5) 75 > (marys-account 5) 185 > (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity) (cond ((equal? activity 'deposit) deposit) ((equal? activity 'withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) > (make-account 100) # > (define acct1 (make-account 100)) > acct1 # > (acct1 deposit) Unsupported Activity : # > (acct1 'deposit) # > ((acct1 'deposit) 50) 150 > (define depositor (acct1 'deposit)) > (depositor 40) 190 > (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity amt) (cond ((equal? activity 'deposit) (deposit amt)) ((equal? activity 'withdraw) (withdraw amt)) (else (error "Unsupported Activity :" activity)))) dispatch) > (define acct2 (make-account 100)) > (acct2 'deposit 20) 120 > (equal? + -) #f > (equal? + +) #t > (define (square x) (* x x)) > (define (square2 y) (* y y)) > (equal? square square2) #f > (equal? square square) #t > (define (square2 x) (* x x)) > (equal? square square2) #f > (define sqaure2 square) > (equal? square square2) #f > ADDENDUM FA 2001 Welcome to DrScheme, version 103p1. Language: Graphical Full Scheme (MrEd). > (load"C:/temp/berk2.scm") open-input-file: cannot open input file: "C:/temp/berk2.scm" (No such file or directory; errno=2) > (load"C:/temp/berk2.scm") #t > (> 4 5) #f > (> 'this 'that) . C:/temp/berk2.scm: 1283.2-1283.33: >: expects type as 2nd argument, given: that; other arguments were: this > (before? 'this 'that) #f > (before? 5 7) #t > (after? 5 7) . reference to undefined identifier: after? > (define (after? x y) (and (not (before? x y)) (not (eq? x y)))) > (after? 5 7) #f > (count '(one two three)) 3 > (define initialize (lambda () (random-seed (current-milliseconds)) (random 72))) define: malformed definition > (initialize) . reference to undefined identifier: initialize > (initialize) . reference to undefined identifier: initialize > (define initialize (lambda () (random-seed (current-milliseconds)) (random 72))) define: malformed definition > (define (initialize) (random-seed (current-milliseconds)) (random 72)) > (initialize) . reference to undefined identifier: | | > (define (initialize) (random 72)) > (initialize) . reference to undefined identifier: | | > (random 72) 31 > (define (initialize) (random 72)) > (initialize) 25 > (quotient 72 24) 3 > (quotient 11 24) 0 > (quotient 71 24) 2 > 10 2 5 10 2 5 > 71 (24 * 2) [23] (8 * 2) [7] (4 * 1) [3] (2 * 1) [1] 71 procedure application: expected procedure, given: 24; arguments were: # 2 > (define mystery (lambda (number l1 l2) (define f1 (quotient number 24)) (define f2 (quotient (- number (* f1 24)) 8)) (define p1 (quotient (- number (* f1 24) (* f2 8)) 4)) (define c1 (quotient (- number (* f1 24) (* f2 8) (* p1 4)) 2)) (define p2 (- number (* f1 24) (* f2 8) (* p1 4) (* c1 2))) (define f1p (cond ((= f1 0) list) ((= f1 1) cons) ((= f1 2) append) ((else (error "Function 1"))))) (define f2p (cond ((= f2 0) list) ((= f2 1) cons) ((= f2 2) append) ((else (error "Function 2"))))) (define c1p (if(= c1 0) l1 l2)) (if(= p1 0) (if(= p2 0) (f1p c1p (f2p l1 l2)) (f1p c1p (f2p l2 l1))) (if(= p2 0) (f1p (f2p l1 l2) c1p) (f1p (f2p l2 l1) c1p))) )) reference to undefined identifier: | | > (define mystery (lambda (number l1 l2) (define f1 (quotient number 24)) (define f2 (quotient (- number (* f1 24)) 8)) (define p1 (quotient (- number (* f1 24) (* f2 8)) 4)) (define c1 (quotient (- number (* f1 24) (* f2 8) (* p1 4)) 2)) (define p2 (- number (* f1 24) (* f2 8) (* p1 4) (* c1 2))) (define f1p (cond ((= f1 0) list) ((= f1 1) cons) ((= f1 2) append) ((else (error "Function 1"))))) (define f2p (cond ((= f2 0) list) ((= f2 1) cons) ((= f2 2) append) ((else (error "Function 2"))))) (define c1p (if(= c1 0) l1 l2)) (if(= p1 0) (if(= p2 0) (f1p c1p (f2p l1 l2)) (f1p c1p (f2p l2 l1))) (if(= p2 0) (f1p (f2p l1 l2) c1p) (f1p (f2p l2 l1) c1p))) )) > (define number (initialize)) > (mystery number '(1 2) '(3 4)) ((1 2) 3 4 1 2) > (define l1 '(1 2)) > (define l2 '(3 4)) > (cons l1 l2) ((1 2) 3 4) > (append l1 l2) (1 2 3 4) > (append l2 l1) (3 4 1 2) > (cons l1 (append l2 l1)) ((1 2) 3 4 1 2) > (define show (lambda (number) (define f1 (quotient number 24)) (define f2 (quotient (- number (* f1 24)) 8)) (define p1 (quotient (- number (* f1 24) (* f2 8)) 4)) (define c1 (quotient (- number (* f1 24) (* f2 8) (* p1 4)) 2)) (define p2 (- number (* f1 24) (* f2 8) (* p1 4) (* c1 2))) (display "mystery ") (display number) (display ": ") (cond ((= f1 0) (display "\(list ")) ((= f1 1) (display "\(cons ")) ((= f1 2) (display "\(append ")) (else (error "First list"))) (cond ((= p1 0) (if(= c1 0) (display "L1 ") (display "L2 ")))) (cond ((= f2 0) (display "\(list ")) ((= f2 1) (display "\(cons ")) ((= f2 2) (display "\(append ")) (else (error "Second list"))) (cond ((= p2 0) (display "L1 L2\)")) ((= p2 1) (display "L2 L1\)"))) (cond ((= p1 1) (if(= c1 0) (display " L1") (display " L2")))) (display "\)") )) define: malformed definition > (define show (lambda (number) (define f1 (quotient number 24)) (define f2 (quotient (- number (* f1 24)) 8)) (define p1 (quotient (- number (* f1 24) (* f2 8)) 4)) (define c1 (quotient (- number (* f1 24) (* f2 8) (* p1 4)) 2)) (define p2 (- number (* f1 24) (* f2 8) (* p1 4) (* c1 2))) (display "mystery ") (display number) (display ": ") (cond ((= f1 0) (display "\(list ")) ((= f1 1) (display "\(cons ")) ((= f1 2) (display "\(append ")) (else (error "First list"))) (cond ((= p1 0) (if(= c1 0) (display "L1 ") (display "L2 ")))) (cond ((= f2 0) (display "\(list ")) ((= f2 1) (display "\(cons ")) ((= f2 2) (display "\(append ")) (else (error "Second list"))) (cond ((= p2 0) (display "L1 L2\)")) ((= p2 1) (display "L2 L1\)"))) (cond ((= p1 1) (if(= c1 0) (display " L1") (display " L2")))) (display "\)") )) > (show number) mystery 41: (cons L1 (append L2 L1)) > (define number (initialize)) > number 2 > (mystery number) procedure mystery: expects 3 arguments, given 1: 2 > l1 (1 2) > l2 (3 4) > (mystery number l1 l2) ((3 4) ((1 2) (3 4))) > (list l2 l1) ((3 4) (1 2)) > (cons l1 (list l2 l1)) ((1 2) (3 4) (1 2)) > (list l1 (list l2 l1)) ((1 2) ((3 4) (1 2))) > (show number) mystery 2: (list L2 (list L1 L2)) > (put 1 1 'this) ok > (get 1 1) this > (get 1 2) #f > (put 'a 'b that) . reference to undefined identifier: that > (put 'a 'b 'that) ok > (get 'a 'b) that > (get 'b 'a) #f > (put -2 -3 'another) ok > (get -2 -3) another > (define (area-circle) 10) > (put 'area 'circle area-circle) ok > (get 'area 'circle) # > ((get 'area 'circle)) 10 > (put '1 '2 'this) ok > (put '1 '3 'this) ok > (put '1 '4 'this) ok > (put '2 '2 '(this is a list)) ok > (put '(1 2) 'stuff) procedure put: expects 3 arguments, given 2: (1 2) stuff > (put '(1 2) '(3 4) 'heavy) ok > (get '(1 2) '(3 4)) heavy > (get 1 3) this > the-get/put-table (*table* ((1 2) ((3 4) . heavy)) (2 (2 this is a list)) (area (circle . #)) (-2 (-3 . another)) (a (b . that)) (1 (4 . this) (3 . this) (2 . this) (1 . this))) > (define (make-square x) (define (dispatch operator) (cond ((equal? operator 'area) (* x x)) ((equal? operator 'perimeter) (* x 4)) (else (error "Operator Not Supported :" operator)))) dispatch) > (make-square 10) # > (define my-square (make-square 10)) > my-square # > (my-square 'area) 100 > (my-square 'perimeter) 40 > (define your-square (make-square 200)) > (your-square 'area) 40000 > (your-square 'perimeter) 800 > (define balance 100) > balance 100 > (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (- balance amount))) > (withdraw 200) Yeah Right > balance 100 > (withdraw 50) 50 > balance 100 > (define balance 50) > balance 50 > (set! balance 40) > balance 40 > (set! my-balance 100) set!: cannot set undefined identifier: my-balance > (define capture (set! balance 200)) > capture > (display capture) # > (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) > balance 200 > (withraw 40) . reference to undefined identifier: withraw > (withdraw 25) 175 > balance 175 > (define (make-withdrawal balance) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) withdraw) (define my-withdraw (make-withdrawal 100)) (define your-withdraw (make-withdrawal 500)) > (my-withdraw) procedure withdraw: expects 1 argument, given 0 > my-withdraw # > your-withdraw # > (my-withdraw 10) 90 > (your-withdraw 20) 480 > (my-withdraw 0) 90 > (my-withdraw 0) 90 > (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity) (cond ((equal? activity 'deposit) deposit) ((equal? activity 'withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) > (define my-account (make-account 100)) > (define your-account (make-account 500)) > my-account # > (my-account 'deposit) # > ((my-account 'deposit) 10) 110 > (define (down x) (cond ((= x 1) (word 1 0)) (else (word x (down (- x 1)))))) > (down 2) 210 > (down 3) 3210 > (define (up x) (up-help x 1)) (define (up-help h l) (cond ((eq? l h) l) (else (word l (up-help h (+ l 1) ) ) ) ) ) > (up 3) 123 > (up 8) 12345678 > (define (downup x) (word (down x) (up x)) ) > (downup 5) 54321012345 > (define (prime? n) (define (dvsr div) (cond ((integer? (/ n div)) (if (= (/ n div) n) #t #f)) (display (dvsr (- div 1))))) (set! div n) (cond ((= n 0) (display #f)) ((< n 0) (display 'ERROR -- NEGATIVE NUMBER)) (else (set! div (- n 1)) (cond ((= (dvsr div) #t) #t) ((= (dvsr div) #f) #f))))) > (prime? 3) . . C:/temp/berk2.scm: 1283.2-1283.33: =: expects type as 2nd argument, given: #t; other arguments were: #t > (define (prime? n) (define (dvsr div) (cond ((integer? (/ n div)) (if (= (/ n div) n) #t #f)) (display (dvsr (- div 1))))) (set! div n) (cond ((= n 0) (display #f)) ((< n 0) (display 'ERROR -- NEGATIVE NUMBER)) (else (set! div (- n 1)) (cond ((eq? (dvsr div) #t) #t) ((eq? (dvsr div) #f) #f))))) > (prime? 3) #t > (prime? 17) #t > (prime? 100) #f > (load "c:\temp\trace.ss") open-input-file: cannot open input file: "c:\temptrace.ss" (No such file or directory; errno=2) > (load "c:/temp/trace.ss") > (trace prime?) (prime?) > (prime? 7) |(prime? 7) |#t #t > (define (prime? n) (define (dvsr div) (cond ((integer? (/ n div)) (if (= (/ n div) n) #t #f)) (display (dvsr (- div 1))))) (set! div n) (cond ((= n 0) (display #f)) ((< n 0) (display 'ERROR -- NEGATIVE NUMBER)) (else (set! div (- n 1)) (cond ((eq? (dvsr div) #t) #t) ((eq? (dvsr div) #f) #f))))) > (define (dvsr div n) (cond ((integer? (/ n div)) (if (= (/ n div) n) #t #f)) (display (dvsr (- div 1))))) > (define (prime? n) (set! div n) (cond ((= n 0) (display #f)) ((< n 0) (display 'ERROR -- NEGATIVE NUMBER)) (else (set! div (- n 1)) (cond ((eq? (dvsr div n) #t) #t) ((eq? (dvsr div n) #f) #f))))) > (trace dvsr) (dvsr) > (dvsr 6 6) |(dvsr 6 6) |#f #f > (dvsr 9 8) |(dvsr 9 8) | (dvsr 8) . procedure dvsr: expects 2 arguments, given 1: 8 > (define (dvsr div n) (cond ((integer? (/ n div)) (if (= (/ n div) n) #t #f)) (display (dvsr (- div 1) n)))) > (dvsr 13 12) #f > (dvsr 12 11) #f > (dvsr 9 8) #f > (dvsr 17 16) #f > (dvsr 16 17) #t > (prime? 17) #t > (prime? 100) #f > (trace dvsr) (dvsr) > (prime? 100) |(dvsr 99 100) | (dvsr 98 100) | |(dvsr 97 100) | | (dvsr 96 100) | | |(dvsr 95 100) | | | (dvsr 94 100) | | | |(dvsr 93 100) | | | | (dvsr 92 100) | | | | |(dvsr 91 100) | | | | | (dvsr 90 100) | | | |[10](dvsr 89 100) | | | |[11](dvsr 88 100) | | | |[12](dvsr 87 100) | | | |[13](dvsr 86 100) | | | |[14](dvsr 85 100) | | | |[15](dvsr 84 100) | | | |[16](dvsr 83 100) | | | |[17](dvsr 82 100) | | | |[18](dvsr 81 100) | | | |[19](dvsr 80 100) | | | |[20](dvsr 79 100) | | | |[21](dvsr 78 100) | | | |[22](dvsr 77 100) | | | |[23](dvsr 76 100) | | | |[24](dvsr 75 100) | | | |[25](dvsr 74 100) | | | |[26](dvsr 73 100) | | | |[27](dvsr 72 100) | | | |[28](dvsr 71 100) | | | |[29](dvsr 70 100) | | | |[30](dvsr 69 100) | | | |[31](dvsr 68 100) | | | |[32](dvsr 67 100) | | | |[33](dvsr 66 100) | | | |[34](dvsr 65 100) | | | |[35](dvsr 64 100) | | | |[36](dvsr 63 100) | | | |[37](dvsr 62 100) | | | |[38](dvsr 61 100) | | | |[39](dvsr 60 100) | | | |[40](dvsr 59 100) | | | |[41](dvsr 58 100) | | | |[42](dvsr 57 100) | | | |[43](dvsr 56 100) | | | |[44](dvsr 55 100) | | | |[45](dvsr 54 100) | | | |[46](dvsr 53 100) | | | |[47](dvsr 52 100) | | | |[48](dvsr 51 100) | | | |[49](dvsr 50 100) | | | |[49]#f | | | |[48]#f | | | |[47]#f | | | |[46]#f | | | |[45]#f | | | |[44]#f | | | |[43]#f | | | |[42]#f | | | |[41]#f | | | |[40]#f | | | |[39]#f | | | |[38]#f | | | |[37]#f | | | |[36]#f | | | |[35]#f | | | |[34]#f | | | |[33]#f | | | |[32]#f | | | |[31]#f | | | |[30]#f | | | |[29]#f | | | |[28]#f | | | |[27]#f | | | |[26]#f | | | |[25]#f | | | |[24]#f | | | |[23]#f | | | |[22]#f | | | |[21]#f | | | |[20]#f | | | |[19]#f | | | |[18]#f | | | |[17]#f | | | |[16]#f | | | |[15]#f | | | |[14]#f | | | |[13]#f | | | |[12]#f | | | |[11]#f | | | |[10]#f | | | | | #f | | | | |#f | | | | #f | | | |#f | | | #f | | |#f | | #f | |#f | #f |#f |(dvsr 99 100) | (dvsr 98 100) | |(dvsr 97 100) | | (dvsr 96 100) | | |(dvsr 95 100) | | | (dvsr 94 100) | | | |(dvsr 93 100) | | | | (dvsr 92 100) | | | | |(dvsr 91 100) | | | | | (dvsr 90 100) | | | |[10](dvsr 89 100) | | | |[11](dvsr 88 100) | | | |[12](dvsr 87 100) | | | |[13](dvsr 86 100) | | | |[14](dvsr 85 100) | | | |[15](dvsr 84 100) | | | |[16](dvsr 83 100) | | | |[17](dvsr 82 100) | | | |[18](dvsr 81 100) | | | |[19](dvsr 80 100) | | | |[20](dvsr 79 100) | | | |[21](dvsr 78 100) | | | |[22](dvsr 77 100) | | | |[23](dvsr 76 100) | | | |[24](dvsr 75 100) | | | |[25](dvsr 74 100) | | | |[26](dvsr 73 100) | | | |[27](dvsr 72 100) | | | |[28](dvsr 71 100) | | | |[29](dvsr 70 100) | | | |[30](dvsr 69 100) | | | |[31](dvsr 68 100) | | | |[32](dvsr 67 100) | | | |[33](dvsr 66 100) | | | |[34](dvsr 65 100) | | | |[35](dvsr 64 100) | | | |[36](dvsr 63 100) | | | |[37](dvsr 62 100) | | | |[38](dvsr 61 100) | | | |[39](dvsr 60 100) | | | |[40](dvsr 59 100) | | | |[41](dvsr 58 100) | | | |[42](dvsr 57 100) | | | |[43](dvsr 56 100) | | | |[44](dvsr 55 100) | | | |[45](dvsr 54 100) | | | |[46](dvsr 53 100) | | | |[47](dvsr 52 100) | | | |[48](dvsr 51 100) | | | |[49](dvsr 50 100) | | | |[49]#f | | | |[48]#f | | | |[47]#f | | | |[46]#f | | | |[45]#f | | | |[44]#f | | | |[43]#f | | | |[42]#f | | | |[41]#f | | | |[40]#f | | | |[39]#f | | | |[38]#f | | | |[37]#f | | | |[36]#f | | | |[35]#f | | | |[34]#f | | | |[33]#f | | | |[32]#f | | | |[31]#f | | | |[30]#f | | | |[29]#f | | | |[28]#f | | | |[27]#f | | | |[26]#f | | | |[25]#f | | | |[24]#f | | | |[23]#f | | | |[22]#f | | | |[21]#f | | | |[20]#f | | | |[19]#f | | | |[18]#f | | | |[17]#f | | | |[16]#f | | | |[15]#f | | | |[14]#f | | | |[13]#f | | | |[12]#f | | | |[11]#f | | | |[10]#f | | | | | #f | | | | |#f | | | | #f | | | |#f | | | #f | | |#f | | #f | |#f | #f |#f #f > =========================================================================== PA-08 =========================================================================== ------------------------------------------------------------------------------- Q1 ------------------------------------------------------------------------------- Send and e-mail message to SICP-Laney@egroups.com asking an INTELLIGENT question about the Programming Assignment, or any other Scheme Programming question. INLUDE SAMPLES of CODE that you are having problems with. Receive your own e-mail, or read your message on-line, and copy your message below. YOUR MESSAGE MUST BE DATED FROM THIS WEEK, SAT-FRI. ------------------------------------------------------------------------------- A1 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q2 ------------------------------------------------------------------------------- PICK someone ELSES quesion and send an inteligent reply to e-groups. Copy the complete message below with date and time and e-mail codes. If a question has been answered already, you may not choose that question, choose another. If all questions have been answered, use the phone list to call a friend, and ask them to post another question for you. You cannot answer your own question. If you find an answer that is incorrect, and CORRECT IT, this will qualify for credit. Don't forget to include the ORIGINAL MESSAGE that you are replying to, showing the persons' e-mail address, date. YOUR MESSAGE MUST BE DATED FROM THIS WEEK, SAT-FRI. ------------------------------------------------------------------------------- A2 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q3 ------------------------------------------------------------------------------- REMOVED ------------------------------------------------------------------------------- A3 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q4 ------------------------------------------------------------------------------- 5. Some banks impose a penalty for excessive withdrawals. Modify the withdraw function to deduct a 1% service fee (of the amount being withdrawn) for each third withdrawal. Or each withdrawal in excess of 3 withdrawals. Listing 7 Expression Outcome (define my-withdraw (make-withdrawal 1000)) my-withdraw (my-withdraw 10) 990 (my-withdraw 10) 980 (my-withdraw 10) 970 (my-withdraw 100) 869 (my-withdraw 865) Error: Yeah Right ------------------------------------------------------------------------------- A4 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q5 ------------------------------------------------------------------------------- 6. Modify the make-account constructor illustrated in listing 8 [below] to permit the account holder to query the object for its balance. Illustrate how the account holder would query the object for its balance. How would you test this fuction with actual data? Listing 8 (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (balance) ... ) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity) (cond ((equal? activity 'Deposit) deposit) ((equal? activity 'Withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) Expression Outcome (define my-account (make-account 100)) my-account (define your-account (make-account 500)) your-account ((my-account 'deposit) 50) 150 ((your-account 'withdraw) 100) 400 ((my-account 'withdraw) 100) 50 ((your-account 'deposit) 10) 410 ((my-account 'borrow) 100) Error: Unsupported Activity: Borrow ------------------------------------------------------------------------------- A5 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q6 ------------------------------------------------------------------------------- 7. In the particular implementation illustrated in listing 8 [above], the object returns the function (known as a method in object terminology) corresponding to the message submitted to the object. Some of you are probably wondering whether this was necessary. Rather than have the object return the method corresponding to the message, to be applied by the applications programmer, perhaps it would be easier to have the object apply the procedure directly to its arguments, in the manner illustrated in listing 9 below. How would this technique work with the "balance" method? Test an example using "balance". Listing 9 Expression Outcome (my-account 'deposit 50) 150 (your-account 'withdraw 100) 400 (my-account 'withdraw 100) 50 (your-account 'deposit 10) 410 (my-account 'borrow 100) Error: Unsupported Activity: Borrow Modify the make-account constructor to work in the manner described above. CLUE: (define (make-account balance) (define (deposit amount) (begin (set! balance (+ balance amount)) balance)) (define (withdraw amount) (if (> amount balance) (error "Yeah Right") (begin (set! balance (- balance amount)) balance))) (define (dispatch activity amount) (cond ((equal? activity 'Deposit) (deposit amount)) ((equal? activity 'Withdraw) withdraw) (else (error "Unsupported Activity :" activity)))) dispatch) ------------------------------------------------------------------------------- A6 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q7 ------------------------------------------------------------------------------- 8. Given our current understanding of Scheme, one of these approaches is more powerful than the other. By this, I mean that there are problems that may be solved using one approach, that may not be solved using the other approach, given the rules of syntax as we know them today. Which approach is the more powerful of the two? Illustrate with an example of a problem that given our current understanding of Scheme, could be solved using one implementation of make-account but not the other. ------------------------------------------------------------------------------- A7 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q8 ------------------------------------------------------------------------------- [Controlling Complexity Lab] 1. Modify the verb conjugation implementation developed in [PA-05] to work using data driven programming techniques (PUT AND GET). Do not redefine the functions devised in the previous assignment. Instead, add the appropriate functions to a table using the put operator, so that they may be invoked using the get or operate procedures. Listing 1 Expression Outcome (define to-laugh (make-regular 'Laugh)) to-laugh (define to-be (make-irregular 'Is 'Am 'Are)) to-be (conjugate 'first-person-singular to-laugh) laughs (conjugate 'third-person-plural to-be) are (se 'I (conjugate 'first-person-singular to-be) 'hungry) (I am hungry) ------------------------------------------------------------------------------- A8 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q9 ------------------------------------------------------------------------------- [Variable State HW] 1. Read Sections 3 - 3.1.3 (Pages 217 - 236) from The Structure & Interpretation Of Computer Programs. 3. What is the value of the variable x defined in the global environment after each of the following procedure applications. (Assume that the effects are cumulative). Don't just guess. Think about which version of x each procedure references. (define x 1) ((lambda () (set! x (+ x 1)))) ((lambda (x) (set! x (+ x 1))) 2) ((lambda (x) (set! x (+ x 1))) x) ((lambda () (define x 3) (set! x (+ x 1)))) ((lambda () (lambda () (set! x (+ x 1))))) ((lambda (x) ((lambda () (set! x (+ x 1))))) 4) ------------------------------------------------------------------------------- A9 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q10 ------------------------------------------------------------------------------- [Controlling Complexity HW] 1. Read Sections 2.4.3 - 2.5.2 (Pages 179 - 202) from The Structure & Interpretation Of Computer Programs. 2. Modify the verb conjugation implementation developed in the previous unit to work using message passing programming techniques. See the examples using a return value of "dispatch". Listing 1 Expression Outcome (se 'I ((make-irregular 'am 'are 'is) 'fps) 'done) (I am done) (define to-be (make-irregular 'am 'are 'is)) (se 'I (to-be 'fps) 'done) (I am done) ------------------------------------------------------------------------------- A10 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q11 ------------------------------------------------------------------------------- LOGIC Two perfect mathematicians, who also happen to be perfect logicians, meet after not seeing each other for some time. Fred: "Hi Kalvin, how are you?" Kalvin: "Oh, great Fred. As a matter of fact, I have three children now." Fred: "Really? How old are they?" Kalvin: "Well, as a matter of fact, the sum of their ages equals your age. and the product of their ages equals the number of windows in that building over there. Can you figure out how old they are, Fred?" Fred: "Um, gee, no, Kalvin, I can't figure their ages given that information." Kalvin: "OK, here is another tidbit for you: my youngest child has red hair." Fred: "Eureka! Voila! Shazam! Holy cow! - I know how old they are now!" QUIZ: HOW OLD ARE THE THREE CHILDREN? ------------------------------------------------------------------------------- A11 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Q12 ------------------------------------------------------------------------------- EXTRA CREDIT 1 Write a Scheme or any language program to solve the logic problem. OR Write an other language program to mimic any scheme program you have written. EXTRA CREDIT 2 Write three midterm problem for Midterm 2. Now that you know the structure of the Midterm problems, creating a problem of your own should be a snap? To create a problem, create a piece of sample code, create solutions A, B, C, D, and E, one of which are CORRECT, and the other 4 are WRONG. AND tell wich specific concept you are TESTING, I.E. conditionals, higer order procedures, etc. Oh, and think how fun it will be to see YOUR problem on the midterm, and you automatically know the answer! More than one problem may be accepted. Have fun! Previous extra credit assignments [especially show-and-tell programsd, and how to save streaming video, real player, windows media player, quicktime on local hard drive] are also still being accepted. ------------------------------------------------------------------------------- A12 ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- End. -------------------------------------------------------------------------------