The PDF version of the book Dynamic Web Development with Seaside is available to download now:
- http://book.seaside.st/book/introduction/pdf-book
At the end of the payment process (PayPal) you will be redirected to the download area where you are able to get the latest builds of the PDF version of the book. If you bookmark the page you will be able to download fixes and extra chapters as we integrate them into the online version. By buying the PDF version you support our hard work on the book.
We wish to thank the European Smalltalk User Group, inceptive.be, Cincom Smalltalk and GemStone Smalltalk for generously sponsoring this book. We are looking for additional sponsors. If you are interested, please contact us. If you are a publisher and interested in publishing this material, please let us know.
I’ll be attending the BlockCamp the coming Saturday in Paris, a joint event between Smalltalk and Ruby. I am prepared to give 3 short presentations:
- Seaside is the framework for developing sophisticated web applications in Smalltalk. This can be either a short introductions into core features of Seaside, or a demo of the new features in the upcoming Seaside 3.0 release.
- PetitParser is a novel parser framework for Smalltalk (and Javascript). It embraces object-oriented design practices (composition, reuse) and combines several existing parser technologies (scannerless parsers, parser combinators, parsing expression grammars, packrat parsers) picking the best parts of each.
- Helvetia is a lightweight approach to embed new languages into a host language and the existing tools. This talk is for people interested into language models, language transformations, and tool integration.
I would like to thank ESUG for sponsoring my trip to Paris. I’ll be around Friday evening, so drop me a line if you’re in Paris and want to meet up. Hope to see you in Paris!
While most people prefer to run SmallLint (Smalltalk Code Critics) from within OmniBrowser, the question arises from time to time on how to do the same from within a workspace script:
1. Select one or more rules to run from the class hierarchy below RBBasicLintRule. For example, the following expression would instantiate a single rule that searches for questionable message sends:
rule := RBBadMessageRule new
The following expression could be used to search for both classes that implement #= but not #hash and methods that do float equality comparisons:
rule := RBCompositeLintRule rules: (Array
with: RBDefinesEqualNotHashRule new
with: RBFloatEqualityComparisonRule new)
2. Next select the scope to run the rules in. In the most simple case this is the complete image:
environment := BrowserEnvironment new
You can however restrict the scope further, for example to the collection hierarchy:
environment := BrowserEnvironment new
forClasses: Collection withAllSubclasses
If you have the OmniBrowser refactoring tools installed you can easily browse a restricted environment by evaluating:
environment open
3. Finally you perform the actual search by evaluating the following expression:
SmalllintChecker runRule: rule onEnvironment: environment
Note that this might take a while depending on the size of the environment and the number of rules you run.
4. If you have the OmniBrowser refactoring tools installed you can have a look at the result by evaluating the following expression:
rule open
The second part of the Superpowers Workshop of the Ottawa Smalltalk user’s group caught my interest. The attendees are discussing on how to implement break and continue in Smalltalk.
Unfortunately the quality of the video was not good enough to be able to steal their example, so I had to build my own. The commented parts should trigger the well known loop operations and continue with the next iteration of the loop, respectively break the execution of the loop.
1 to: 5 do: [ :index |
index = 2
ifTrue: [ ].
index even
ifTrue: [ ].
Transcript show: index; cr ]
The above example exercises the two hypothetical constructs. If you execute the code in your brain you should print out the numbers 1 and 3 on the transcript.
The first possible solution that comes to my mind are exceptions. Smalltalk has very powerful exceptions that can do all kind of magic things, but here we just need to signal and catch them at the right place. I created two new exception classes ContinueLoop and BreakLoop, then I put a handler inside the loop to continue, and a handler outside the loop to break. This gives us the first working solution. Admittedly it looks very ugly:
[ 1 to: 5 do: [ :index |
[ index = 2
ifTrue: [ ContinueLoop signal ].
index even
ifTrue: [ BreakLoop signal ].
Transcript show: index; cr ]
on: ContinueLoop
do: [ :err | ] ] ]
on: BreakLoop
do: [ :err | ]
Somebody of the Ottawa Smalltalk user’s group suggested to use continuations and they eventually come up with a pretty complicated solution. In fact, if you have the Seaside classes loaded in your image, the use of continuations provides a pretty strait-forward solution to the problem. You wrap the complete loop into a continuation to break, and the body of the loop in a continuation to continue. Evaluating the block arguments break and continue jumps right to the place after you created the respective continuations and resumes execution from there. This gives us the expected behavior:
Continuation currentDo: [ :break |
1 to: 5 do: [ :index |
Continuation currentDo: [ :continue |
index = 2
ifTrue: [ continue value ].
index even
ifTrue: [ break value ].
Transcript show: index; cr ] ] ]
The solution is quite readable, but it basically uses a sledgehammer to crack the nut. Also continuations are pretty heavyweight to use in tight loops like this, because they essentially create a snapshot of the complete execution stack. And in this example we are not interested into the stack at all, we just want to jump back to the place where the continuation was defined. Luckily jumping back is something plain old Smalltalk blocks can do as well:
withEscaper: aBlock
aBlock value: [ ^ nil ]
This small helper methods evaluates aBlock and passes another block into it that returns nil. It is important to note that a return in Smalltalk always returns from the lexical scope, that means it returns from the method the return was defined in. In this example, evaluating the block [^ nil ] returns from the method #withEscaper:. Of course, this only works if the method, #withEscaper: is still on the execution stack (if not, we had to use continuations).
We can use the above helper method to implement the final version of our loop. This time without using magic, but simple and fast Smalltalk blocks:
self withEscaper: [ :break |
1 to: 5 do: [ :index |
self withEscaper: [ :continue |
index = 2
ifTrue: [ continue value ].
index even
ifTrue: [ break value ].
Transcript show: index; cr ] ] ]
The open-source book Pharo by Example has been announced. It is a new, improved and adapted version of Squeak by Example to Pharo, the new Smalltalk that is quickly approaching its 1.0 release. One of the particularly exciting additions to the book is the chapter Seaside by Example.