Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!mips!spool.mu.edu!news.cs.indiana.edu!ux1.cso.uiuc.edu!m.cs.uiuc.edu!cs.uiuc.edu!voss From: voss@cs.uiuc.edu (Bill Voss) Newsgroups: comp.lang.smalltalk Subject: Re: method-ology Message-ID: Date: 22 Jun 91 08:10:49 GMT References: Sender: news@m.cs.uiuc.edu (News Database (admin-Mike Schwager)) Organization: Typed Smalltalk Group, Dept of Comp Sci, Univ of IL in Urbana. Lines: 106 In-Reply-To: peters@sirius.UVic.CA's message of 21 Jun 91 17: 32:02 GMT Nntp-Posting-Host: laslo.cs.uiuc.edu peters@sirius.UVic.CA (Doug Peters) writes: > (I learned a lot from that "accessing methods" discussion a while back). Uh oh, here we go again. ;-) [Note: My site's news feed will be down Sunday-Wed, but email will be ok.] > For example, I have a Matrix class, and I want to have a qr method > that decomposes the receiver into (you guessed it) two matrices > traditionally labelled "q" and "r". > > Should I > a) modify the receiver to become the "r" matrix and answer the "q" > b) leave the receiver and answer a size two array containing two matrices > c) have a q:r: method whose parameters become the desired results > d) some permutation of the above > ? > a) modify the receiver to become the "r" matrix and answer the "q" That tends to be dangerous. You probably have a couple of variables around which contain the "original" matrix, and will get very confused when it "changes behind their back." (Remember, you normally only have a POINTER to an object.) > b) leave the receiver and answer a size two array containing two matrices This is a very common solution. Quick and dirty, but at least it is simple to implement. > c) have a q:r: method whose parameters become the desired results Getting closer. This type of thing is usually written as something like: | tmpQ tmpR | tmpQ := MyMatrix new. tmpR := MyMatrix new. theMatrix q: tmpQ r: tmpR. Programmers who anticipate that as unlikely as it seems today, somebody might someday subclass MyMatrix write: | tmpQ tmpR | tmpQ := theMatrix class new. tmpR := theMatrix class new. theMatrix q: tmpQ r: tmpR. > d) some permutation of the above How about some permutation from the access method discussion. You could use DOUBLE DISPATCHING. Add the Matrix method qr: anObject | newQ newR| ... ...... "You implied you already had this code" ... anObject q: newQ r: newR. ^self and add the q:r: methods to whoever needs "q" and "r". If you want to be even more general (but somewhat more obscure) you could instead add to Matrix the method: qr: anObject perform: aSymbol | newQ newR| ... ...... "You implied you already had this code" ... anObject perform: aSymbol with: newQ with: newR. ^self ======================================================================= An entirely different approach. ======================================================================= > When should methods: > a) modify the receiver -or- > b) modify method parameters Sometimes. ;-) More seriously, frequently it is useful to ensure that once created, an instance never seems to change. (Obviously this is not always desirable.) Numbers are generally an example of this, where all the methods return new instances instead of changing state. The biggest advantage of such immutable instances is that the programmer does not need to worry about who references the instance. The biggest disadvantage (in borderline cases where you could do things either way) is usually the copy cost. Most of the time you make a new "immutable" instance you are copying most of the state from an existing instance. If your Matrix class is implemented as an "immutable" class, then the "q" and "r" matrices are also "immutable." In that case You could move "qr" into "private" and have it update two instance variables "q" and "r" then add two access methods: returnQ q isNil ifTrue: [self qr]. ^q and the same for a returnR method. WARNING: See previous "accessing methods" discussion for warnings about using access methods! They still apply! that should generate some discussion! Bill Voss