[Seaside] Backtracking within tasks using continuations

Lukas Renggli renggli at gmail.com
Wed May 30 06:56:58 UTC 2007

> Okay, to date I've made a very slick navigation interface for my Seaside webapp
> using a WAPath to 'bookmark' the users progress within a WATask. My WATask
> produces continuation objects, which it adds to the WAPath, and these allow the
> user to step backwards in the WATask progression.

I guess you have your own custom WAPath implementation. Mine does not
have a method #empty and does not perform anything when being
clicking. It only provides an accessor to get the current navigation

> The WATasks go method is included at the end of this post if it helps you to
> understand what I mean.

Why don't you extract your code into extra methods? Your code is
almost impossible to read with all the duplicated functionality:

call: aComponent named: aString
	^ super call: (Continuation currentDo: [ :cc |
		path pushSegment: (Array with: cc with: aComponent) name: aString.
		cc value: aComponent ])

Furthermore, the last line within your continuation block seems
useless. You could also just write:

call: aComponent named: aString
	^ super call: (Continuation currentDo: [ :cc |
		path pushSegment: (Array with: cc with: aComponent) name: aString.
		aComponent ])

> This navigation method works flawlessly IF, and only IF, all the continuations
> placed on the path are produced only within the WATasks method (i.e. -- if you
> invoke a subtask, any anchors it adds to the path become invalidated once the
> subtask answers.

This is because evaluating a continuation does not restore the state
(but just the execution stack) of your application, in your case the
parent task does not restore its previously called child.

To solve your problem I would try to manually restore the required
state. Something like that could possibly work:

call: aComponent named: aString
	| states |
	states := WASnapshot new.
	root visiblePresentersDo: [ :e | e updateStates: states ].
	^ self call: (Continuation currentDo: [ :cc |
		path pushSegment: (Array with: cc with: states with: aComponent)
name: aString.
		aComponent ])

> Originally, I had thought that this had something to do with answer
> continuations from seaside, somehow surviving with the subtask and causing the
> subtask to return immediately again once I'd invoked a continuation that would
> return us to within that subtask -- but now I think the problem is much simpler:
> Since subtasks involve a call/answer method using continuations, once you invoke
> that answer continuation, its like you never made the call in the first place --
> so my continuation produced by the subtask probably gets garbage collected.

No. That cannot be the case because you can always use the back button
to return to a page that has already been answered.

> If this is the case, that kind of sucks (in a program compositional way), since
> I can't split my task into reusable subtasks and still use this navigational
> methodology (and this navigational methodology is really too awesome for words)
> -- UNLESS there is a way to call/answer from one task to a child task without
> using continuations.

Sure, check out my recent post with the subject "Seaside on VA
Smalltalk?". There I present a way to replace #call: with
#show:onAnswer: that doesn't use continuations. However this won't
solve your the problem either ...


Lukas Renggli

More information about the seaside mailing list