cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ovidiu Predescu <>
Subject Re: [RT] Managing Flow and Resources
Date Thu, 03 Jan 2002 01:27:09 GMT
Hi Judson, and Happy New Year!

[I've Cc-ed the mailing list as well.]

I hope this reply does not come too late ;-), but I left on holidays
the day after you sent the message, and didn't have time to respond to

On Thu, 20 Dec 2001 13:28:57 -0600, Judson Lester <> wrote:

> On Wednesday 19 December 2001 04:17 pm, you wrote:
> > On Wed, 19 Dec 2001 13:41:58 -0600, Judson Lester <> wrote:
> <snip/>
> > > > But at the same time, would it be even better if you didn't have to
> > > > think about it altogether and program like you'd do for your command
> > > > line?
> > >
> > > Being able to avoid the management of the session would help a lot.
> > > And yes, minimizing the amount of new pardigm to be learned would
> > > make everything gravy.  Putting desktop developers in a position to
> > > quickly be coding web apps is veryt attractive.
> >
> > The biggest difference from a normal programming language are these
> > hidden non-local exits, which are somewhat equivalent to a goto
> > instruction. It's quite a tricky, yet powerful mechanism.
> I'm not so sure it's very tricky.  It seems to me that it ought be presented 
> more as a special 'System.exit().'  And for that reason, I wonder if there 
> ought to be a 
> send-response-page(...) 
> and
> send-exit-page(...)
> or something, on the grounds that it distinctly seperates an exit point and 
> an 'instruction.'  This raises the assocaited question: ought not "response 
> pages" have a different structure from an "exit-page"?  And how?  Or is every 
> send-page() call a potential exit (a reasonable assumption, since it 
> might/should include a navigation option, which would break the flow)?  And 
> what about the reverse: is every send-page(exit.xml) a potential response 
> returned?
> Answering my own question: it seems most sensible that every
> send-page(query.xml) be a potential exit (with the issues of clean
> up variables, etc.) and that a send-page(exit.xml) not be allowed to
> return (and so should be a different call: to send-exit-page(...)
> for instance).
> It's actually the send-page(query.xml) call that concerns me more, since I 
> think any semantic component of the flow-language will need to be considered 
> in the following context: "What if this is used across a send-page(...) and 
> the send page doesn't return?"  I'm reminded of finally clauses in Java 
> exception handling.

I don't think we can have a distinction between an exit page and a
"normal" page. In fact you can have pages that have both exit links,
and returning links. The distinction between the pages in not in the
way they are invoked (send-page vs. send-exit-page), but in the
information encoded in the page, which is and _should be_ external to
the control flow logic.

An application developer should not be concerned with "What if this is
used across a send-page(...) and the send page doesn't return?". It is
very possible that the user may not hit the "continue" URL on the
page, thus doing a non-local exit in a different context of the
application. At some point the application framework will invalidate
and garbage collect the continuation object, making the URL reference

That's why I said the model is very much different than what we are
used to, and may be difficult to grasp.

> <snip>Because someone has too</snip>
> > > Another, equally valid question is what will emphasize SoC, and keep
> > > business logic in its place (with the subquestion: what relationship
> > > do flow and business logic have?  I propose that they are not
> > > identical, and that their intersection should be limited to flow's
> > > dependance on business logic)?  If variable assignment must come
> > > from Java code, because flow units can't return anything, it becomes
> > > very difficult to use flowmaps for business logic.
> >
> > I argue that we do need to have functions that return values. I've
> > shown in a previous message how such functions are useful.
> >
> > The distinction between flow and business logic is a bit blurry, and I
> > would say it's probably not a good idea to remove functionality from
> > the language just to enforce separation of concerns. Why should a
> > calculator application for example need to use Java to do it's logic,
> > when the flow logic can do additions and substractions? I think we
> > should let the developer choose the right mix he/she wants. This may
> > lead to messy programs in the beginning, but with the right patterns
> > explained to people, I think it's easier for people to write using the
> > right mix.
> >
> To borrow an aphorism: FS.  I'd be very leery of a system where a
> language designed to control the flow of complex requests could be
> used to easily implement a calculator.  The power of the best
> systems comes from the simplicity and ease of use.  I'd say it's
> definitely not a good idea to add functionality that doesn't
> directly serve the purpose of the language because it might be
> useful.
> <aside>If it were hard, I could cope.  For an example of what I
> please qv Inform and the Z-Machine.  Short version: Inform is a
> language for writing Adventure style 'interactive fiction', but if
> you're willing to code directly in the assembly language of the
> ZMachine, you can get it to play Tetris.</aside>


That's right. Nevertheless, I think it's much harder to come up with a
restricted language which has everything you need to do _only_
business logic, than to have a powerful language. For the later, it's
enough to translate that language to Scheme. For the former, you need
quite a bit of work to remove the "unnecessary" functionality out of
the language. But then how do you know you're not limiting the
expressiveness and power of the language by doing so? A user using the
system in a different way than you expected might need that little
thing you've decided is not important.

> > > > If, at the end, it comes out that it's easier to use sessions, we'll
> > > > happily forget about continuations.
> > >
> > > Reflection leads me to ask, though: is the idea I'm suggesting of
> > > continuation-based "flow units" (I have a hard time thinking of them
> > > as "functions" without returns) differ significantly from FSM/goto
> > > programming?  The difference I can see is that state transitions are
> > > seperated from input, which is fairly significant in my mind, and
> > > almost exactly what is wanted.
> >
> > The way I see the non-local exits of the functions with no return, is
> > that they take the program out the current context. It's like doing a
> > system.exit(), and starting from a different place. It is more like
> > forcing the program take on a different flow, than moving to a
> > different state.
> This is a much clearer and, I think, more accurate analogy than likening 
> non-local exits to goto statements.  You get one last gasp of a message 
> ("exit(NULLPOINTERERROR); == send-exit-page("sorry-couldnt-register.xml");) 
> and then the overarching System takes control again.
> > Or at least this is how they should be used, and I believe you can
> > enforce this model by giving programmatic access only to the current
> > continuation, not to the past ones. This way the programmer cannot
> > jump to an arbitrary existing continuations, only to the last one,
> > which will resume the execution of the program. This avoids the goto
> > stigma, where you can have jumps to different parts of the program.
> For clarity, the equivalent of (call/cc thunk) is send-page(xyzzy.xml); right?

Yes. send-page() needs to associate the continuation object with a
URL, so that when the request is sent back, the system can find the
continuation object. It looks like this:

(define current-continuations (make-hash-table))

(define send-page
  (lambda (page pipeline object-model)
     (lambda (k)
       (let ((url (k->url k)))
	 (hash-put object-model 'k-url url)
	 (hash-put current-continuations url k)
	 (cocoon/process page pipeline object-model)

(define handle-request
  (lambda (request)
    (let* ((url (request-get-url request))
	   (k (hash-get current-continuations url)))
      (if k
	  (k request)
	  (cocoon/process "error.xml" "error-pipeline" nil)))))

The 'current-continuations' hash table maintains an association
between URLs and continuation objects.

The send-page function takes as arguments a page, a pipeline and an
object-model hash table, which contains data to be put in the
generated page during the initial content generation. The function
passes its continuation to a function which generates a new URL for
it, puts the URL <-> continuation association in the
'current-continuations' hash table, processes the output page through
the pipeline, and then kills the current executing thread. The URL of
the continuation is passed to the generator of the pipeline, so it can
incorporate it in the generated page (this URL will point to the rest
of the computation).

When a request is received from the client, the continuation
associated with the URL is obtained and invoked. This will effectively
resume the computation after the corresponding send-page().

In practice, the handle-request will be invoked by the sitemap
logic. Each sitemap will have a hidden first entry for obtaining a
continuation from a given URL. I'm currently working on having the
sitemap logic completely implemented in Scheme, so that things are
easier (for me ;-) to write.

Ovidiu Predescu <> (inside HP's firewall only) (my SourceForge page) (GNU, Emacs, other stuff)

To unsubscribe, e-mail:
For additional commands, email:

View raw message