
In the chapter entitled 'Building Abstractions with Data' in 'Structure and Interpretation of Computer Programs', the rational number object is introduced (Sec. 2.1.1.)... http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-13.html ... except not as "objects", but in terms of procedures and data, with the data structure in question being the "pair" i.e. a (numerator, denominator) tuple, with relevant procedures for forming such pairs (cons) and extracting either (car, cdr). What you're left with is a sense of data on the one hand, and procedures for operating on that data on the other. I miss the higher level abstraction of "object", in which the relevant procedures are encapsulated, along with the data structure, such that our interface to the "rational number object" contains whatever functionality we like. Plus I miss the ability to easily override primitive operators, such that I can multiply, add, subtract rational numbers (a.k.a. fractions) using *, + - etc. This is an important abstraction in math -- to realize that these operators may be redefined at will (yet usually according to various rules of group theory, e.g. whatever * means, there should be an identity object ident such that anyobj * ident = anyobj = ident * anyobj). In the Python approach, we might begin in the "wishful thinking" stage by sketching out a shell object: class Rat: def __init__(self,p,q): self.numer = p self.denom = q def __add__(self,other): pass def __sub__(self,other): pass def __mul__(self,other): pass
a = Rat(2,3) a.numer 2 a.denom 3
and so on. We'll also want to have a way of representing rational numbers to the screen, along the lines of: (define (print-rat x) (newline) (display (numer x)) (display "/") (display (denom x))) i.e. def __repr__(self): return "%s/%s" % (self.numer,self.denom)
a = Rat(2,3) a 2/3
And so on. I prefer this approach, because we're setting up a class definition, not a sandbox of procedures and data, with the procedures tied to the data simply by the programmer's knowledge and/or by documentation. The class definition is itself a kind of data structure, in that it files the relevant methods with the data, under the same heading. No one has to keep track of what procedures "belong" with what data. That's built in to the class definition. Furthermore, we're setting up an inheritable framework. A subclass could pick up where Rat leaves off, and further elaborate methods -- perhaps it would simply have a different representation scheme, outputting "mixed" fractions e.g. 5 1/4 instead of 25/4. This is commonly done with a global variable switch, but a subclass would work. In the case of Matrices, any ol' Matrix object would by nxm, with a subclass, Sqmatrix, being for nxn or square matrices -- where only these latter have certain methods, such as determinant and inverse. I guess I'm feeling uneasy with a foundational approach that doesn't bring in the concept of objects closer to the beginning. The object concept is an important one. Just procedures and data, without objects, seems a rather scattered/cluttered approach. Shouldn't newcomers learn the object model right about where this rational numbers example is presented? Certainly building rational numbers as objects would be a standard exercise in a Python-focused curriculum (might be a math class -- if the distinction matters). Kirby
participants (1)
-
Kirby Urner