Squeak: In Praise of Learning

Squeak!

Updated: Apr 25, 1998.

in Japanese

  1. Free Documents for Smalltalk by the Most Revd AOKI.
  2. Smalltalk tips? by Dr. MASUDA Hidetaka.
  3. Squeak Idioms by the Most Revd AOKI.

on this page

  1. Squeak's current limitations
  2. Favorite Squeak Hints
  3. Cannot compile - stack including temps is too deep
  4. Attempt to evaluate a block that is already being evaluated.
  5. Inexactness in the Float printing method
  6. Cannot use Temporaries in block
  7. A good rule of thumb


Squeak's current limitations

from comp.lang.smalltalk:
Obviously Squeak has many rough edges, compared to VisualWorks for example, of which these stand out as perhaps the worst:
  • slow speed (1/20 - 1/40 C, compared to 1/2 - 1/6 C for VW)
  • lack of easily available tutorials & training
  • lack of standard exception handling
  • a state of flux regarding the GUI (w/Morphic)
  • lack of GUI widgets you might expect (and they look odd too)
  • lack of various OS hooks in Smalltalk itself (like OLE)
  • various bugs (like timing issues w/ the debugger and opening a window)
  • lack of domain objects you might expect, like value models
  • lack of block-scoped block arguments
  • lack of team / ENVY support

Favorite Squeak Hints

Mr. Ted Kaehler talks:
Folks, In February, I mentioned how wonderful Command-m and Command-n are. Select any selector and do Command-m to see its implementors (Alt-m on a PC or Unix). Select any selector and do Command-n to see its senders (Alt-n on a PC or Unix). It works in any text window.

This time, I'm urging you to use two variants of the browser window. In the class list pane of the browser, select a class and choose "spawn hierarchy". A hierarchy browser shows all the superclass and subclasses of a class in the class list pane. Very useful for jumping around and seeing what the class inherits. Try it.

Another great view on code is found in the message list pane. Look at any method, and choose "more..." from the menu (in the message list pane). Then choose "browse method hierarchy", the top item. It brings up a message list window with the current method and all inherited versions. This is especially useful then the method has super in it, or when you can't remember the inheritance chain, or when you want to see how this methods is implemented more generally by a superclass. (In the next release, this item will be called "method hierarchy" and will be on the first message list menu, instead of on its second layer.)

Cannot compile - stack including temps is too deep

The problem here is that Squeak contexts only come in two sizes:

  • smallFrame: 12 slots
  • largeFrame: 32 slots
smallFrames cover 94% of all methods, and including largeFrames gets you to 99.975%, but it turns out that the number of temporaries plus the max stack depth in your method or source is just a bit larger than a largeFrame allows.

Since Squeak allocates a unique temp for each temp name, you might try modifying the code for that method to "reuse" temp names, where possible, instead of using a unique temp name.

Thanks to Mr. Tim Olson.

Attempt to evaluate a block that is already being evaluated.

Mr. Tim Olson taught me again,

The implementation of Blocks in Squeak currently does not allow recursive invocation of blocks, because of the way they are implemented (they are not full closures, yet). Ian's Jitter uses a Dynamic Context Cache which assigns each block invocation its own context local to the VM, so basic recursive blocks will run, but do not yet fully interact correctly with things that examine contexts, like the Debugger.

If you want to run the code under the non-jitter VM, you will have to replace the recursive block with a recursive method.

Mr. Tim Rowledge taught me,

That's because you are doing a recursion on a blcok - which the conventional VM cannot do (cf. blue book) whereas the jitter can as it has the framework in place for working from Closures instead of blocks. I'm sure Ian could add much more detail if you need it.

If you need to run with the conventional vm, rewrite the code to avoid the block recursion. Of course, since it is intended to test the efficiency of recursively calling a block, that would be fairly pointless !

Inexactness in the Float printing method

7853 asFloat asString returns '7852.99999999999'

This is due to some inexactness in the Float>>absPrintOn:base:digitCount: method. I noticed this awhile back, and was working on a new Float printing method that would print these values exactly (as well as correctly round the printed value) -- see Float>>testPrintOn:base: in the 1.31 image. This method is still a work-in-progress; it prints the significand followed by an 'e', followed by the exponent, rather than formatting the printString correctly. It also is a bit slower than the existing absPrintOn: method.

I've got a handle on yet another Float printing algorithm; it is the one used by the GNU gcc library, so it could be a pretty good replacement.

Thanks to Mr. Tim Olson.

Cannot use Temporaries in block

| collection |
collection := SortedCollection new.
Smalltalk allBehaviorsDo: 
	[:each |
	| boolean |
	boolean := each isMeta not and: [each isFixed].
	boolean ifTrue: [collection add: each name]].
^ collection
You can't accept or do it using Temporaries in block, like above. You will be warned that "Period or right bracket expected ->". So move temporaries in block out of block, like below.
| collection boolean |
collection := SortedCollection new.
Smalltalk allBehaviorsDo: 
	[:each |
	boolean := each isMeta not and: [each isFixed].
	boolean ifTrue: [collection add: each name]].
^ collection

A good rule of thumb

Mr. Ian Piumarta talks:

The two "standard" Squeak benchmarks are ancient, dating back to medieval times when knights were bold and VMs were slow and hardware crawled along at a few tens of MHz. These days the "traditional" parameters to these benchmarks are utterly useless, since the results get swamped (as in the above example) by quantisation errors and boundary effects introduced by a number of factors.

A good rule of thumb might be: if the benchmark takes less than 10 seconds to run, increase the parameters (and adjust the scaling as appropriate). For example, "32 benchFibs" would be much better on most platforms compared to "26 benchFibs". "benchmark" needs a little more care, since the initial 5000000 (or whatever) must be scaled by the same number as the iteration count. E.g:

        5000000 / (Time msToRun: [10 benchmark])
becomes:
        25000000 / (Time msToRun: [50 benchmark])
and so on.


Created: Mar 16, 1998.