6.001 Structure and Interpretation of Computer Programs. Copyright o 2004 by Massachusetts Institute of Technology Slide 13.1.6 One view of Data Here is a simple example to illustrate this point. Suppose I have a set of different geometric objects, things like numbers, lines Some complex structure constructed from cons cells shapes, and I want to write a procedure, or an operation, that Explicit tags to keep track of data types mplement a data abstraction as set of procedures that will scale each of those objects by some amount. Then a perate on the data generic operation, under the data-directed approach would look Generic"operations by looking at types like this procedure shown here. Given an object and my desired scale factor, I use the type of the object to dispatch: if it is a cond ((number? x)(* x factor)) number, I just multiply; if it is a line, I ship it to the procedure that will scale a line and so on (else (error unknown type)))) The point of this example is that I think about things in terms of 6 001 SICP I the kinds of objects I have and procedures for manipulating each distinct object type. I use the tag or the type of the object to tell me which procedure to send the object to Slide 13.17 Dispatch on Type So now let's go back to our questions. How easy is it to extend such a system, a system where we are breaking things up into Adding new data types Must change every generic operation tagged data, and using data directed programming? First, if we add a new data type to our system, what do we have to do? Adding new methods Just create generic operations Well we can see from our example that we will have to all the procedures like scale, to add a new clause to each cond dispatching on that new type of object. As a consequence, if there are many such procedures, we have a lot of changes to nake, both a great deal of code to write, and more importantly aking sure that we change all the relevant procedures If we add a new operation or method what do we need to do? This is easier, as we just need to develop a subprocedure for each type of object to which the method will apply Thus in this style of programming, adding a new data type is painful, while adding a new method is reasonable. As when the changes are mostly new methods or operations, or when the different kinds of data structures in the or a consequence, this approach to modularizing systems works best when there are only a few data abstractions system are mostly independent of one another. In those cases, this style of approach works well. But not everything fits these cases What should we do in those cases? Slide 13.1.8 Adding new data types So let's step back from this organization for a second. One way Must change every generic operation to think about structuring a large system is to realize that we are Must keep names distinct Adding new methods likely to have a large number of different data objects( Just create generic operations stances of data abstractions ) and a large number of operations we want to perform on those objects. Conceptually ata type 1 Data type 2 Data type 3 Data tyt this means we have a big table, where we can use a different operation 1 Some proc Some proc some proc Some proc row for each operation we want to perform, and a different peration 2 Some proe Some proc Some proc Some proc column for each kind of data abstraction we have. Then at each peration a some proc some proc some proc some proc element in this table, we can conceptualize having a specific Operation 4 Some proc Some proe Some proc Some proe procedure, intended to perform the particular operation(e.g scaling )on the particular kind of data object(e. g. a number)6.001 Structure and Interpretation of Computer Programs. Copyright © 2004 by Massachusetts Institute of Technology. Slide 13.1.6 Here is a simple example to illustrate this point. Suppose I have a set of different geometric objects, things like numbers, lines, shapes, and I want to write a procedure, or an operation, that will scale each of those objects by some amount. Then a generic operation, under the data-directed approach would look like this procedure shown here. Given an object and my desired scale factor, I use the type of the object to dispatch: if it is a number, I just multiply; if it is a line, I ship it to the procedure that will scale a line, and so on. The point of this example is that I think about things in terms of the kinds of objects I have and procedures for manipulating each distinct object type. I use the tag or the type of the object to tell me which procedure to send the object to. Slide 13.1.7 So now let's go back to our questions. How easy is it to extend such a system, a system where we are breaking things up into tagged data, and using data directed programming? First, if we add a new data type to our system, what do we have to do? Well we can see from our example that we will have to all the procedures like scale, to add a new clause to each cond, dispatching on that new type of object. As a consequence, if there are many such procedures, we have a lot of changes to make, both a great deal of code to write, and more importantly making sure that we change all the relevant procedures. If we add a new operation or method, what do we need to do? This is easier, as we just need to develop a subprocedure for each type of object to which the method will apply. Thus in this style of programming, adding a new data type is painful, while adding a new method is reasonable. As a consequence, this approach to modularizing systems works best when there are only a few data abstractions or when the changes are mostly new methods or operations, or when the different kinds of data structures in the system are mostly independent of one another. In those cases, this style of approach works well. But not everything fits these cases. What should we do in those cases? Slide 13.1.8 So let's step back from this organization for a second. One way to think about structuring a large system is to realize that we are likely to have a large number of different data objects (or instances of data abstractions), and a large number of operations we want to perform on those objects. Conceptually, this means we have a big table, where we can use a different row for each operation we want to perform, and a different column for each kind of data abstraction we have. Then at each element in this table, we can conceptualize having a specific procedure, intended to perform the particular operation (e.g. scaling) on the particular kind of data object (e.g. a number)