Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
A Newbie's on-going tutorial
Last updated at 6:40 pm UTC on 14 October 2006
mergeMe into Squeak Cookbook

Welcome! My name is Michael Guenter and I am new to Squeak and Object Oriented Programming. I made a request for a Study Buddy / Tutor a while back, and Bob Arning has most graciously consented to give me some of his time. The content of "A Newbie's On-going Tutorial" is the result of our discussions.

Comment: This is a wonderful page! Kudos to Michael for newbie bravey and Bob Arning for the wonderful responses. Add your email address, Michael, if you would? – Doug Clapp


How this page is organized:

This Swiki page displays the questions I pose and the answers/suggestions/advice that Bob provides in chronological order with the most recent inquiries at the bottom of the page. Topic names and subjects for each inquiry are provided to make it easier for other Newbies to get the information they need, for example:

A Newbie's on-going tutorial Adding files to my image
Squeak How-To: Updating my image


For more general inquiries, something like:
Squeak Programming: Inheritance

I am currently working on developing two applications:

- a game called Trailblazer, and
- a database for Student health information.

Any questions I pose regarding these applications will be indicated as follows, for example:

Game, Trailblazer: User Interface
Game, Trailblazer: Setting up arrays
Game, Trailblazer: Randomly determining Planet characteristics
Database, Student Health: Making a table


There is also a special topic called Today's Discovery. This topic contains journal entries describing personal insights and discoveries.

This page of the On-going Tutorial contains all inquiries and responses. If, however, you would like to browse by topic, click on the topic of your choice above (in blue and underlined).



Squeak Programming: Re-using Objects

Q: My first question is: Are there any Objects that I could re-use to create a user-interface for Trailblazer and/or Student Health Database? What are they?

R: Well, the obvious answer is yes – you will be using all sorts of morphs, collections, blocks, etc. In terms of the highest level of the interface, check out the BobsUIv2 and spreadsheet1 projects on BSS for some ideas. Additionally, as needs become clear, you will often see something in the image that's similar that you can borrow from. As an example, you might look at EToyProjectDetailsMorph and EToyProjectQueryMorph. To see an example of the first, hold down the Publish button on the navigator until the menu appears and select 'edit project info'. For the second, hold down the Find button and select 'search the SuperSwiki'.

Game, Trailblazer: Building the User Interface

Q: I want to build a user-interface. I have borrowed objects for helpText (from SameGame) etc., and I thought I might start with the buildButton method from SameGame and modify it according to my needs. If I want to re-use other code, where should/could I start?

R: One suggestion would be to

Squeak How-To: Updating my Image

Q: I have a copy of your BobsUIv2.cs.gz (and the version 3.0 update, from the BobsUI page). How do I install this into the image I am currently using?

R: You have two possible options:

1. Use these two files.
2. Use the project on BSS.

Squeak How-To: Updating versions

Q: How do versions work? If I have an image that I have been using (and adding to) for 3.0, but then I want to upgrade to 3.1, do I have to make a use a 3.1 image, and if so, can I just upload my changes file from my older image into the 3.1 image and in that way hang on to all new code that I have added?

R: You can (in theory) do it either way.

- You file out all your code changes as change set(s) and then file them into a 3.1 image.

- You can simply request updates from the 3.0 image and go all the way to a current 3.1.

There are some problems with the second approach, however. The servers providing updates got mangled a few months ago and they may not have been restored with all the requisite updates, so the first may be the only one that will work in this case.

Today's Discovery: 09 July '01
I have been trying to cut and paste the buildButton method from SameGame to MyStuff Trailblazer. However, every time I try to save, I get unknown variable messages (color, for example). When I changed the superclass name from Object to AlignmentMorph, suddenly color was no longer an unknown variable.

In Squeak, many classes are already made for us. That is why Squeak OO programming truly features re-usable code. I understand this a little better now.

I understand now that my challenge is to learn what classes are available and what they do, and then select the appropriate superclass! :)

Squeak Programming: Working with an ever-changing system: Object (code) durability.

Q: Is programming for Squeak like trying to hit a moving target? I have been following the Mailing list posts and one of the threads that caught my eye was

"WindowFrame design"http://people.we.mediaone.net/trade/WindowFrames.htm.

The work talked about in this thread is exciting, but it makes me wonder, would the objects being discussed be added to Squeak, or would they replace other objects?

If they replace other objects, software for Squeak would have to constantly be updated because the old objects are no longer there (e.g., the BankAccount tutorial has had to undergo some changes because of changes in Squeak Classes).

If, on the other hand, new objects are added to the system, does this not affect execution performance/speed of applications? On a similar topic, what are the criteria for deciding whether changes made constitute a version name change?

More importantly, how often are version changes allowed (again with the moving target idea).

A: There are several possible answers to this question. First, no, it is not a moving target. If you download a Squeak image, it is under your complete control. You can keep running the same image for the next decade if you like. You'll miss interesting new developments, but you will have a stable base for your development. You can always selectively include interesting updates, sometimes easily and sometimes not.

Second, yes, it is a moving target. Squeak is an ongoing exploration of new ideas in making computers more useful. Some experiments are dropped when they don't work out (although you can always find the dropped code in an older image and reinstall it if it's something you really like).

Having given these two very clear answers, the truth is that an effort is made to minimize breakage caused by updates, both in terms of what's in the image and in terms of what has been published in Squeak projects. The steps involved in maintaining this backward compatibility will aid your in keeping you private code updated as well.

Squeak Programming: Object/Class/Method documentation

Q: What are the expectations as regards documentation, when people add system level objects/classes to Squeak? When I look at a Class, for example, AlignmentMorph, there is some double quote explanations provided, but not nearly enough to let me know what is going on, or how I should use that class.

A: Depends on who is doing the expecting. Some folks value separate documentation highly and others do not. Personally, I much prefer using the tools in Squeak to see how something is being used rather than reading how someone thought it would be used at some time in the past. Documentation rarely keeps pace with code, so I tend to trust the code. If you want to know how to use a class, searching for references to the class (control-n in the class list pane of a browser) will usually pull up all sorts of interesting examples. Using an explorer on an interesting morph will yield tons of information about how it is put together.

Game, Trailblazer: Printing 'Hello World' in a Window

Q: How can I get Squeak to create a window (not the transcript) and print 'Hello World' in it? Ultimately, I would like to have Squeak create a window that changes in size to meet the requirements of the length of the string.

A: StringHolder new contents: 'Hello, world'; openLabel: 'not the transcript'.
(more)

Game, Trailblazer: Creating Random Values

Q: I want Squeak to pick a random number between 1 and 6. Then I want it to find a corresponding string from a list of 6 strings, and then print the corresponding string in the transcript or a window. How could I do this?

A: Transcript show: #('alpha' 'beta' 'gamma' 'delta') atRandom.

Game, Trailblazer: Displaying Random Values in a Window

Q: How can I combine the above two processes so that my randomly selected string appears in my new window?

A:
StringHolder new
	contents:#('alpha' 'beta' 'gamma' 'delta') atRandom;
	openLabel: 'Your Window'

Today's Discovery: 02 August '01
I have been trying to figure out a way to simulate the random value (sum) that would be generated from simultaneously throwing three six-sided dice. The probabilities of a given sum (e.g., 3, 4, 5,..17, 18) differ and to calculate these probabilities (and then have an object that picks random values according to these probabilites) requires complicated math.

What I realized while reading Mark's book was that if I create a single six-sided die object, then I could use other objects to request values from the six-sided die object and sum the results (e.g., If I wanted to simulate 3 six-sided dice, I could have an object make 3 requests for a value from the die object. Then, this new object could sum the three values and automatically I would be given a value between 3 and 18 and with the same probabilities as simultaneously throwing 3 dice).

This does not tell me the probability of a given value, but it does provide me with the value (adhering to the corresponding probabilities), and that is all that I am after. This involves no probabilities math and is also very reusable.

Or just try

((1 to: 3) collect: [:e | 6 atRandom]) sum


Squeak Programming: Numbers

Q: What does the :e and the | do in the above example?

A: In a block (something within square brackets), the :e means the first argument passed to the block will be known inside the block as 'e'. The vertical bar is simply a sign that the list of argument names is complete. In the specific example above, we don't really care what the argument is (it will be 1, then 2, then 3), but we need to tell the block to expect it anyway since #collect: expects a 1-argument block.

Squeak Programming: Syntax

Q: What is the difference between the semi-colon and the period? When I tried using the code below with a period, I received a "Nothing more expected" message.

StringHolder new
     contents:#('alpha' 'beta' 'gamma' 'delta') atRandom;
     openLabel: 'Your Window'

A: A period separates statements. A semi-colon separates messages that will be sent to the same receiver. Thus

   a b ; c; d.

will send #b to a, then send #c to a and finally send #d to a.

On the other hand,

   a b . c . d.

will send #b to a. (period, end of statement). After that, "c" is a separate statement (if it makes any sense). And then "d" is another statement.

Squeak Programming: Variables

Q: Is the e in the block below what is called a variable?

((1 to: 3) collect: [:e | 6 atRandom]) sum.  

If so, could I create another object that asked for the value of e and then selected a corresponding string from a list of strings? e.g.,

3 = 'industrial goods', 4 = "precious metals', ...18 = 'luxury goods'.

A: The e in the block is a variable, more specifically a "block argument". Other variables are

Now to answer the question about using the block argument to access a particular value, you could do

blk := [ :e | #('v1' 'v2' 'industrial goods' 'precious metals') at: e].

then, if you wrote

str := blk value: 3.

str would contain 'industrial goods' .

However, this looks like something that might useful for more than one method, so I would be inclined to do something a bit different. Perhaps define a class variable, perhaps called CommodityNames. Initialize this variable like so:

CommodityNames := Dictionary new.
CommodityNames at: 3 put: 'industrial goods'.
CommodityNames at: 4 put: 'precious metals'.
...etc...

Then any method in the class could simply say

str := CommodityNames at: someNumber.

However (once again), you are likely to be doing various things with these commodities, so it may make sense to define a Commodity class and use instances of this class, each of which knows its name, price range, usability for various tasks, etc. Then, rather than passing around simple integers to represent commodities and then needing to translate those integers, you would simply pass the commodities themselves around.

Game, Trailblazer: Description for Modeling Purposes

Q: One of the reasons I have wanted to automate some of the administration of Trailblazer is because it requires the use of so many unique tables and lists. Because of the numerous tables and lists, it is difficult to design classes and objects that will reflect efficiency in coding.

Here is a brief description of the one of the game elements and corresponding administration tasks, Space Exploration.

There are five possible planet types that can be discovered (Classes B,C,D,E, and F). Upon planet "discovery", the Planet class must be determined using three six-sided dice and then consulting the corresponding table (e.g, 3-4 is a "B class" planet, 5-7 is a "C class" planet, etc.).

From here, the player must determine (through dice rolling and table consulting): a) how many goods are produced, b) what those goods are, c) what the price multiple is for these goods, and d) the quantity available of each given good.

The player must then determine in similar fashion: a) how many goods are consumed, b) what those goods are, and c) what the demand letters and modifiers are for those goods.

After much thought, I have decided that it would probably be easiest to duplicate the tables as is. How could I go about creating these tables so that other objects could consult them?

Here are some example tables:

Planet Class Determination (3 six-sided dice)

Roll Class
3-4 B
5-7 C
8-11 F
12-16 D
17-18 E

Number of Goods Produced

Roll Class
B C D E F

1 1 1 1 0 0
2 2 1 1 1 0
3 2 1 1 1 1
4 3 2 1 1 1
5 3 2 2 2 2
6 3 3 2 2 2

Planet B Class Goods Produced List (3 six-sided dice)

3 'missionaries'
4 'precious minerals & metals'
5 'recreational drugs'
6 'luxury consumer goods'
7 'bulk consumer goods'
8 'medical equipment'
9 'industrial equipment'
10 'bulk food'
11 'industrial minerals & metals'
12 'medical drugs'
13 'weapons'
14 'labor'
15 'liquors'
16 'entertainment'
17 'art'
18 'luxury foods'

Note: Each Planet Class has two unique lists (consumption and production). While the actual goods are the same, the order in the list (and thus the probability of being chosen as one of the goods) is different. Thus, there are ten unique lists with unique probabilities for the goods.

A: While I still think there may be some useful classes lurking in this, you could implement these lists as class methods in TrailblazerTables, e.g. Thus,

pickAPlanetClass
^'xxBBCCCFFFFDDDDDEE' at: self roll3Dice

would allow you to say

thisPlanetClass := TrailblazerTables pickAPlanetClass

Number of Goods Produced is a relatively simple table so it might go like this:

pickNumberOfGoodsProducedFor: aLetter
aLetter = $B ifTrue: [^#(1 2 2 3 3 3) at: self roll1Die].
aLetter = $C ifTrue: [^#(1 1 1 2 2 3) at: self roll1Die].
...etc...

Then you could write somewhere else

numGoods := TrailblazerTables pickNumberOfGoodsProducedFor: thisPlanetClass

The goods produced and consumed could be done in a similar fashion or you could create a class variable to hold them all and then the code to access them might look like

typeOfGoodsProducedFor: aLetter
^(TypeOfGoodsList at: aletter) at: self roll3Dice


Squeak Programming: Workspace and System Browser

Q: Why is it that the following code works in the Workspace but cannot be saved in the System Browser? (After the first 'classBPlanetGoodsConsumed' I receive a 'Nothing more expected' message when I try to save it as a method in the System Browser.)

classBPlanetGoodsConsumed := Array new.
classBPlanetGoodsConsumed := classBPlanetGoodsConsumed, #('v1'
'v2'
'missionaries'
'precious minerals & metals'
'recreational drugs'
'luxury consumer goods'
'bulk consumer goods'
'medical equipment'
'industrial equipment'
'bulk food'
'industrial minerals & metals'
'medical drugs'
'weapons'
'labor'
'liquors'
'entertainment'
'art'
'luxury foods').
^classBPlanetGoodsConsumed at:3.


A: Code that you run in a workspace need only be valid expression(s) while methods saved in a browser also need a name (or more correctly, a method header) for the method so, if you put this in a browser

pickBPlanetGoodsConsumed

| classBPlanetGoodsConsumed |

classBPlanetGoodsConsumed := Array new.
classBPlanetGoodsConsumed := classBPlanetGoodsConsumed, #('v1'
'v2'
'missionaries'
'precious minerals & metals'
'recreational drugs'
'luxury consumer goods'
'bulk consumer goods'
'medical equipment'
'industrial equipment'
'bulk food'
'industrial minerals & metals'
'medical drugs'
'weapons'
'labor'
'liquors'
'entertainment'
'art'
'luxury foods').
^classBPlanetGoodsConsumed at:3.

Of course, there is no real need to define a variable here, so it would be simpler to write

pickBPlanetGoodsConsumed

^#('v1' ..etc.. 'luxury foods') at:3

NEW QUESTION!

Squeak Programming: Objects communicating

Q: How do I get one object to ask for something from another object? I don't understand how they get values/information from each other (i.e., how they communicate). For example, if I had a rollDice object (method), how would I get another object to call on the rollDice object to provide a value that could be used for a given purpose? I guess I am just really impressed with the reusability of this method
((1 to: 3) collect: [:e | 6 atRandom]) sum
as opposed to the simplicity and relevance (for my purposes) of this method

pickAPlanetClass
^'xxBBCCCFFFFDDDDDEE' at: self roll3Dice
In the second example, I don't need any communication between objects. In the first, however, I would need to have separate objects communicating back and forth.

A: The specific answer in this case is to implement a method in the same class as the pickAPlanetClass method
roll3Dice
^((1 to: 3) collect: [:e | 6 atRandom]) sum
The up-arrow says to return the value of the expression, so that's what "self roll3Dice" will evaluate to. Maybe a nicer solution would be to implement a class Dice. Then add some class methods like
roll3
^((1 to: 3) collect: [:e | 6 atRandom]) sum
and then you could say anywhere in your code
   x := Dice roll3

The more general answer is that all methods return a value. If a return statement is encountered (an up-arrow followed by an expression), then the value of that expression is returned. If the end of the method is encountered without hitting an explicit return, then the value of the received is returned.