From: ···········@yahoo.com
Subject: Unexpected Behavior in (lml2:html ...), Bug or (Mis)Feature?
Date: 
Message-ID: <1163019707.732095.28450@i42g2000cwa.googlegroups.com>
I ran into some frustrastion trying to use lml2. My package uses
net.aserve and lml2 (instead of htmlgen).

In htmlgen, one might use the following:

(with-http-response (request entity)
  (with-http-body (request entity)
    (html ...)))

I verified that with htmlgen the browser receives the html via the
assigned localhost port. However, using lml2, the browser shows a blank
page, because the html goes to *standard-output*. To make it work as
expected, one needs to assign *html-stream*, using whatever method,
such as (lml2:html-stream ...), as in the following:

(with-http-response (request entity)
  (with-http-body (request entity)
    (html-stream (request-reply-stream request)
      (html ...))))

Of course, package net.aserve uses package net.html.generator, which
exports *html-stream*, a special variable, so when
net.aserve:with-http-body assigns *html-stream* with LET, *html-stream*
is also special. Yes? Package lisp-markup-language-2 (lml2) also
exports special variable *html-stream*, so in a package using lml2 and
the algorithm in the first example *html-stream* refers to a different
*html-stream* (???), making it necessary to assign the imported
*html-stream* with lml2:html-stream. Right?

Since lml2 is a fork of htmlgen, why wouldn't one expect the two
packages to behave identically? Does aserve's dependence on htmlgen
preclude identical usage? Or is it a bug or misfeature in lml2 that it
doesn't behave identically?

As a workaround, I wrapped the call to html-stream in a fork of Peter
Seibel's define-url-function (from Chapter 26 of "Practical Common
Lisp"), which instead uses a macro called with-html-output, because it
depends on a different html-generation facility.

The lack of documentation and discussion of lml2 on the web meant that
to understand the unexpected behavior and to work out a solution I had
to analyze the internals of more than one library. I did find one
example which demonstrated assigment to *html-stream*--without a word
explaining the need to do so. The apparent lack of popularity of the
lml2 library might explain the lack of discussion, but I have noticed
the same issue in other Common Lisp endeavors. The power and usefulness
of the language has me hooked. Should it require so much legwork and so
many brain cycles to get anything done?

~

From: ·············@gmail.com
Subject: Re: Unexpected Behavior in (lml2:html ...), Bug or (Mis)Feature?
Date: 
Message-ID: <1163077827.819255.325680@h54g2000cwb.googlegroups.com>
I can't reproduce your example, but I think I understand where the
problem is. The macro with-http-body probably binds/assigns
net.html.generator:*html-stream*, that is, the variable identified by
the symbol *html-stream* in package net.html.generator. But lml2 looks
for the contents of lml2:*html-stream*, which is a symbol lying in the
package lml2, i.e. the two *html-stream* symbols are different and
identify different variables.
So yes, you have to bind lml2:*html-stream* with
net.html.generator:*html-stream* in the body of with-http-body, like
you have done by calling (html-stream ...). Probably simply doing (let
((lml2:*html-stream* net.html.generator:*html-stream*)) ...) might do,
but again, I can't test it so don't take this for granted :)
And yes, it seems aserve's dependence on htmlgen precludes identical
usage, as long as you use the with-http-body macro... you might write
your own, I'm thinking something like

(defmacro with-my-http-body (request entity &body body)
  (let ((rq (gensym)) (ent (gensym)))
    `(let ((,rq ,request) (,ent ,entity))
       (with-http-body ,rq ,ent
         (html-stream (request-reply-stream ,rq)
          ,@body)))

I'm not an expert in Lisp, so this macro could be dramatically wrong --
but at least I hope you'll understand what I mean :)

cheers
alessio s.
From: ···········@yahoo.com
Subject: Re: Unexpected Behavior in (lml2:html ...), Bug or (Mis)Feature?
Date: 
Message-ID: <1163287103.033529.212500@i42g2000cwa.googlegroups.com>
·············@gmail.com wrote:
> I can't reproduce your example, but I think I understand where the
> problem is. The macro with-http-body probably binds/assigns
> net.html.generator:*html-stream*, that is, the variable identified by
> the symbol *html-stream* in package net.html.generator. But lml2 looks
> for the contents of lml2:*html-stream*, which is a symbol lying in the
> package lml2, i.e. the two *html-stream* symbols are different and
> identify different variables.
> So yes, you have to bind lml2:*html-stream* with
> net.html.generator:*html-stream* in the body of with-http-body, like
> you have done by calling (html-stream ...). Probably simply doing (let
> ((lml2:*html-stream* net.html.generator:*html-stream*)) ...) might do,
> but again, I can't test it so don't take this for granted :)
> And yes, it seems aserve's dependence on htmlgen precludes identical
> usage, as long as you use the with-http-body macro... you might write
> your own, I'm thinking something like
>
> (defmacro with-my-http-body (request entity &body body)
>   (let ((rq (gensym)) (ent (gensym)))
>     `(let ((,rq ,request) (,ent ,entity))
>        (with-http-body ,rq ,ent
>          (html-stream (request-reply-stream ,rq)
>           ,@body)))
>
> I'm not an expert in Lisp, so this macro could be dramatically wrong --
> but at least I hope you'll understand what I mean :)
>
> cheers
> alessio s.

Thanks for your input, verifying and paraphrasing my suspicions.

Whereas I can understand that lml2's redefinition of *html-stream*
decouples lml2 from htmlgen, I must wonder why the need for decoupling
exists, when it doesn't seem to be necessary to tie aserve and htmlgen
together so tightly, when one could have simply bound [a non-special]
html-stream with a LET, etc, or even a named parameter (as in
with-open-file, etc.) in net.aserve:with-http-body. Is this tight
coupling between aserve and htmlgen a necessary feature, and for what
specific reason...? Or was it a questionable design decision on the
part of the AllegroServe developer(s)? Making *html-stream* an exported
special variable and referring to it within with-http-body
unnecessarily complicates using aserve with an html-generation facility
other than htmlgen, and unless someone identified a valid reason for
doing so (e.g. security?) this smells like a poor design. Unnecessarily
tying the hands of the user of any facility in this manner looks truly
stupid at first and second glances--unless, of course, there was a very
good reason that I haven't definitively identified. Granted, other
CL-based web-server options exist, but every option involves different
pros and cons. 

~