Ken Tilton <kentilton@gmail.com> wrote:
+---------------
| >> And too bad, Lisp could have used a good web framework.
+---------------
Strange. I hacked together one that was quite adequate [for the
needs of the sites I had to support] in a very short amount of time,
and I wasn't even an experienced CL programmer at the time [though
I did have several years of Scheme usage, including for web stuff].
+---------------
| Ray Dillinger wrote:
| > Ehh, tomayto, tomawto. Continuation-based web programming is
| > a technique. It works. There's really no problem with choosing
| > it over some other techniques, nor with choosing other techniques
| > over it.
|
| You read my mind. Today I was thinking it does not bother me that anyone
| wants to use continuations, what bothers me is that that arguable choice
| (to be debated soon at Lispvan) led to some poor soul deciding to write
| C instead of Lisp. (To get to the stack so he could do continuations in
| his homebrewed language.)
+---------------
As I discussed at ILC'03 with Christian Quennec (who mostly agreed),
it's not "real" continuations *per se* that's important, it's the
*idea* of web continuations that's important. Once you've grokked
that idea, you can still program in CL [or anything else] by simply
reifying externalizable markers for your "continuations", and then
dispatching on them when they come back in.
In fact, "real" continuations *are* somewhat harmful, since they
imply a *single* place a.k.a. flow-of-control to re-enter when the
user clicks "Submit". Often one needs pages with several *different*
HTML forms in them, each with a different "continuation" to evoke.
If you use "real" continuations you are then forced to add an
explicit dispatch layer... but if you do *that*, you might as
well be using the simple "pseudo-continuations" I use, which are
just tokens [stored in hidden form variables] containing the
"Where do I want to go now?" information.
Said another way, my simple web framework contains the following:
;;;
;;; Web Continuations Module (well, the feeble beginnings of one).
;;;
;;; Within an HTML <form>, (BUILD-CONTINUATION :var1 "val1" :var2 "val2")
;;; will pass "var1=val1&var2=val2" in the CGI bindings.
;;; Includes automatic debug-state propagation.
(defun build-continuation (&rest rest &key (stream *standard-output*)
&allow-other-keys)
(with-html-output (s stream t)
(loop for (name value) on rest by #'cddr
and first = t then first do
(unless (eq name :stream)
(when (and first *debug*)
(setf first nil)
(htm "[debug = " *debug* ", k = {" name "," value "}]" :br (lfd)
(:input (:type "hidden" :name "debug" :value "yes")) (lfd)))
(htm (:input (:type "hidden" :name name :value value)) (lfd))))))
and a typical usage might be like so [the :STATE is the critical bit]:
(defun search-type2-page (stream self results bindings)
(with-html-output (s stream t)
(:form (:method :post :action self)
(build-continuation :stream s :state "type2-results"
:m_ci "yes" :m_pm "no")
(:b () "1. Select how much to display:") :br (lfd)
(:table (:border 0 :cellpadding 0)
(:tr () (:td ()
(:input (:type "radio" :name "m_sel" :value "min"
:checked nil))
"Name & email only." (lfd)
(:input (:type "radio" :name "m_sel" :value "mid"))
"Name, email, & phones." (lfd)
(:input (:type "radio" :name "m_sel" :value "max"))
"All columns." (lfd))))
...The rest of the page...)))
It's been "continuations" enough for me... ;-} ;-}
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607