From: Dustin Withers
Subject: Keywords and CL-WHO
Date: 
Message-ID: <1158817824.186992.53300@i3g2000cwc.googlegroups.com>
I have a list representation of a purchase order (specifically an ASC
X12 850).  All the segments and elements are broken into lists of
lists.  This works well for parsing but I'm running into a problem
turning the the first string in an element into a keyword (with the :
on the front) that can be accepted by CL-WHO:with-html-output.

(cl-who:with-html-output (*standard-output* nil :prologue t)
	   (:html (:body "test")))

Produces:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html><body>test</body></html>

So knowing the little about keywords that I do I thought this would
work:

(cl-who:with-html-output (*standard-output* nil :prologue t)
	   ((intern "FOO" :keyword) (:body "test")))

and return:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><foo><body>test</body></foo>

Instead it returns:
; in: LAMBDA NIL
;     ((INTERN "FOO" :KEYWORD) (:BODY "test"))
;
; caught ERROR:
;   illegal function call
;
; compilation unit finished
;   caught 1 ERROR condition

Sorry for my ignorance but can anyone explain where my thinking is
wrong?  I'd like to produce an XML document of the data that I have.

Thanks,
-dustin

From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <dfSdnW0ndM5T7Y_YnZ2dnUVZ_rednZ2d@speakeasy.net>
Dustin Withers <·········@gmail.com> wrote:
+---------------
| I have a list representation of a purchase order (specifically an ASC
| X12 850).  All the segments and elements are broken into lists of
| lists.  This works well for parsing but I'm running into a problem
| turning the the first string in an element into a keyword (with the :
| on the front) that can be accepted by CL-WHO:WITH-HTML-OUTPUT.
+---------------

Short answer: Ain't gonna work. [Not as stated, at least.]

Medium answer: You're going about it the wrong way, but since you
seem already prepared to write code transform a parsed XML tree
into keywords [wrong approach] you should also be up to the task
of writing the code needed to transform a parsed XML tree directly
into strings of HTML output [right approach].

Much longer answer:
It appears that you are confusing macroexpansion time [which is
either part of compile-time or evaluation-time (for interpreted
code)] with run-time -- when the Common Lisp code actually executes.

CL-WHO:WITH-HTML-OUTPUT is a *macro* which is intended to be used
on literal [constant] source code forms at macroexpansion time, not
on dynamically-built structures at run-time. It does not evaluate its
&BODY argument; it *rewrites* it into Lisp code which the CL system
then compiles (or evaluates) in the usual fashion. Since a list that
begins with a keyword is not legal CL source code, WITH-HTML-OUTPUT
borrows that illegal format to use for itself as a marker that rewriting
is needed. Any literal input list or sublist *not* beginning with a
keyword (or a sublist beginning with a keyword) is passed straight
through to the CL system unmodified.

+---------------
| (cl-who:with-html-output (*standard-output* nil :prologue t)
| 	   (:html (:body "test")))
| 
| Produces:
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
| <html><body>test</body></html>
+---------------

Right. But now let's look at *how* that happened:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue t)
 	  (:html (:body "test"))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
	(WRITE-STRING
	 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html><body>test</body></html>"
	 *STANDARD-OUTPUT*)))
    T
    > 

That is, then entire (:HTML (:BODY "TEST")) subform got transformed --
at macroexpansion time!! -- into a single literal string. But as noted
above, if there are forms *not* beginning with keywords, they're just
passed through, permitting the intermingling of Lisp code with template
writing, which can be very useful, e.g.:

    > (import '(cl-who:htm cl-who:fmt)) ; for brevity

    T
    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue t)
 	  (:html
	    (:body
	      (loop for i from 1 to 5 do
		(htm "test #" (fmt "~d" i) (:br)))))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
	(WRITE-STRING
	 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html><body>"
	 *STANDARD-OUTPUT*)
	(LOOP FOR I FROM 1 TO 5
	      DO (PROGN
		   (WRITE-STRING "test #" *STANDARD-OUTPUT*)
		   (FORMAT *STANDARD-OUTPUT* "~d" I)
		   (WRITE-STRING "<br />" *STANDARD-OUTPUT*)))
	(WRITE-STRING "</body></html>" *STANDARD-OUTPUT*)))
    T
    > 

Again, after the macro expands, all of the original (illegal) "keyword
forms" are gone, transformed into a legal CL program form. And then
when you *execute* that form [newlines added to output for clarity]:

    > (progn (eval *) (values))
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html><body> test #1<br />test #2<br />test #3<br />test #4<br />
    test #5<br /></body></html>
    > 

So to repeat, any CL code in the WITH-HTML-OUTPUT &BODY does run
at run-time, but *all* of the "keyword" stuff was removed [well,
transformed] by the macro at macroexpansion time.

And in any case, if your CL code is compiled there's no
WITH-HTML-OUTPUT left at run-time to pass your document to.

+---------------
| So knowing the little about keywords that I do I thought this would work:
| 
| (cl-who:with-html-output (*standard-output* nil :prologue t)
| 	   ((intern "FOO" :keyword) (:body "test")))
+---------------

Before trying to evaluate this, let's macroexpand it first:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue t)
 	  ((intern "FOO" :keyword) (:body "test"))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
	(WRITE-STRING
	 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
	 *STANDARD-OUTPUT*)
	((INTERN "FOO" :KEYWORD) (:BODY "test"))))
    T
    > 

Oops! Look at that form after the WRITE-STRING, which CL-WHO *didn't*
rewrite, since it didn't start with a keyword:

    ((INTERN "FOO" :KEYWORD) (:BODY "test"))

That's not legal Common Lisp, on several counts. No wonder your CL
implementation complained about it.

+---------------
| Sorry for my ignorance but can anyone explain where my thinking is
| wrong? I'd like to produce an XML document of the data that I have.
+---------------

One naive way would be to try to call the internal routine
CL-WHO::TREE-TO-COMMANDS at run-time with your munged-up
parsed XML tree, and then EVAL that, e.g.:

    (eval (cl-who::tree-to-commands (replace-tags-with-keywords my-tree)
				    *standard-output*
				    cl-who::*prologue*))

In the immortal words of a disgraced politician: "But that would
be wrong." Much better would be to simply walk the parsed XML tree
yourself, writing the output as text -- in essence, "unparsing" the
ML document. That is, instead of writing a REPLACE-TAGS-WITH-KEYWORDS
routine [which you were going to write anyway, yes?], write a
WRITE-TREE-AS-XML-TEXT routine. Hint: The code for the two is
*very* similar...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <UZvQg.255$OM3.169@newsfe11.lga>
Rob Warnock wrote:
> Dustin Withers <·········@gmail.com> wrote:
> +---------------
> | I have a list representation of a purchase order (specifically an ASC
> | X12 850).  All the segments and elements are broken into lists of
> | lists.  This works well for parsing but I'm running into a problem
> | turning the the first string in an element into a keyword (with the :
> | on the front) that can be accepted by CL-WHO:WITH-HTML-OUTPUT.
> +---------------
> 
> Short answer: Ain't gonna work. [Not as stated, at least.]

This may be going too far.


> Much longer answer:

Nice! But...

> It appears that you are confusing macroexpansion time [which is
> either part of compile-time or evaluation-time (for interpreted
> code)] with run-time -- when the Common Lisp code actually executes.

Nah, it just so happens that cl-who does not evaluate that particular 
argument. They could have written in differently and then the OP would 
be all set.

I do not use cl-who, but if I were in the OP's situation, I would cross 
my fingers and examine the source to with-html-output. It might expand 
into CALL-WITH-HTML-OUTPUT, which /would/ handle the runtime value of 
the argument. If not, I would uncross my fingers so I can use the 
keyboard to hack a CALL-WITH-HTML-OUTPUT out of WITH-HTML-OUTPUT.

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <YqudnU7DxdE6CI_YnZ2dnUVZ_tydnZ2d@speakeasy.net>
Ken Tilton  <·········@gmail.com> wrote:
+---------------
| Rob Warnock wrote:
| > Dustin Withers <·········@gmail.com> wrote:
| > It appears that you are confusing macroexpansion time [which is
| > either part of compile-time or evaluation-time (for interpreted
| > code)] with run-time -- when the Common Lisp code actually executes.
| 
| Nah, it just so happens that cl-who does not evaluate that particular 
| argument. They could have written in differently and then the OP would 
| be all set.
+---------------

But... but... it's the &BODY argument of a *macro*. Macro arguments
*aren't* evaluated!

[Aside: HTOUT (and presumably, HTMLGEN as well) does it exactly the
same way as CL-WHO. (Sub)Forms starting with keywords are rewritten
into executable CL code; other (sub)forms are left as is. The final
result is returned from the macro and compiled/evaluated as usual.]

+---------------
| I do not use cl-who, but if I were in the OP's situation, I would cross 
| my fingers and examine the source to with-html-output. It might expand 
| into CALL-WITH-HTML-OUTPUT, which /would/ handle the runtime value of 
| the argument.
+---------------

Not really. Here's the entire definition of WITH-HTML-OUTPUT:

    (defmacro with-html-output ((var &optional stream
				     &key prologue
					  ((:indent *indent*) *indent*))
				&body body)
      "Transform the enclosed BODY consisting of HTML as s-expressions
    into Lisp code to write the corresponding HTML as strings to VAR -
    which should either hold a stream or which'll be bound to STREAM if
    supplied."
      (when (and *indent*
		 (not (integerp *indent*)))
	(setq *indent* 0))
      (when (eq prologue t)
	(setq prologue *prologue*))
      `(let ((,var ,(or stream var)))
	,(tree-to-commands body var prologue)))

The only important bit is the last two lines. Note that whatever
TREE-TO-COMMANDS returns is spliced into the code. No evaluation
whatsoever is done to BODY before being handed to TREE-TO-COMMANDS,
so what the OP wanted to do simply isn't possible. [At least, not
using the WITH-HTML-OUTPUT macro.]

+---------------
| If not, I would uncross my fingers so I can use the keyboard
| to hack a CALL-WITH-HTML-OUTPUT out of WITH-HTML-OUTPUT.
+---------------

Go back and look at my suggestion *not* to call TREE-TO-COMMANDS
directly:

      +--- The really ugly bit.
      |
      V
    (eval (cl-who::tree-to-commands (replace-tags-with-keywords my-tree)
                                    *standard-output*
                                    cl-who::*prologue*))

Given that MY-TREE is generated at *run-time* from reading an XML
document [he mentioned a purchase order -- presumably all possible
purchase orders are not known at compile time], do you really want
him to be calling EVAL there, at run-time? ...when a simple tree-walk
of MY-TREE could output the desired text *without* any use of EVAL?


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <E0zQg.4$Pr4.0@newsfe10.lga>
Rob Warnock wrote:
> Ken Tilton  <·········@gmail.com> wrote:
> +---------------
> | Rob Warnock wrote:
> | > Dustin Withers <·········@gmail.com> wrote:
> | > It appears that you are confusing macroexpansion time [which is
> | > either part of compile-time or evaluation-time (for interpreted
> | > code)] with run-time -- when the Common Lisp code actually executes.
> | 
> | Nah, it just so happens that cl-who does not evaluate that particular 
> | argument. They could have written in differently and then the OP would 
> | be all set.
> +---------------
> 
> But... but... it's the &BODY argument of a *macro*. Macro arguments
> *aren't* evaluated!

Of course not. I was speaking loosely. The question is simply "Can i use 
(intern "HTML" :keyword) instead of :html?" Comes up a lot when using 
unfamiliar APIs (well, ok, sometimes also my own). Then we ask 
ourselves, is that argument evaluated or not? /In the expansion./

Here, try this:

Does cl-who expand into code such that a given argument gets evaluated, 
or does it quote that argument in the expansion?

Now if you complain that keywords do not have to be quoted....

<g>

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <-q-dnQuGAbx8_47YnZ2dnUVZ_o-dnZ2d@speakeasy.net>
Ken Tilton  <·········@gmail.com> wrote:
+---------------
| Rob Warnock wrote:
| > But... but... it's the &BODY argument of a *macro*. Macro arguments
| > *aren't* evaluated!
| 
| Of course not. I was speaking loosely. The question is simply "Can i use 
| (intern "HTML" :keyword) instead of :html?"
+---------------

The answer, at least for CL-WHO, HTOUT, AllegroServe's HTML, and
maybe some others, is "No". [At least, not without reaching *deep*
under the covers and playing with the internals of the implementation.]

+---------------
| Here, try this:
| Does cl-who expand into code such that a given argument gets evaluated, 
| or does it quote that argument in the expansion?
+---------------

Neither, really, or a mixture of both, depending on your viewpoint.
CL-WHO is a *compiler* from "HTML-designating forms" into "HTML-emitting
Common Lisp code". That is, the &BODY argument of WITH-HTML-OUTPUT
expands into pure "inline" Lisp code, primarily WRITE-STRINGs with
constant [well, computed at macroexpansion time] strings as arguments.
A form such as (:FOO "some text") gets compiled into:

    (write-string "<foo>some text</foo>")

while ((:FOO :ATTR1 "val1" :ATTR2 "val2") "some more text") gets
compiled into:

    (write-string "<foo attr1='val1' attr2='val2'>some more text</foo>")

and (:FOO subforms... ) gets compiled into:

    (progn (write-string "<foo>")
	   ,@(translation-of subforms...)
	   (write-string "</foo>"))

Moreover, CL-WHO tries very hard to aggregate all adjacent output
constant strings into as few strings as possible, e.g.:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue nil)
          (:html (:head (:title "A small test page"))
		 (:body (:h1 "Test Page")
			"This is only a test."))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
       NIL
       (WRITE-STRING
	"<html><head><title>A small test page</title></head><body><h1>Test Page</h1>This is only a test.</body></html>"
	*STANDARD-OUTPUT*)))
    T
    >

See? The *entire* "keyword tree" is gone, replaced by a single
constant string.

Obviously, when one allows Lisp code into the template, the same
degree of collapsing can't be done, but it tries as best it can:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue nil)
          (:html
	    (:head (:title "A small test page"))
	    (:body (:h1 "Test Page")
		   (loop for i from 1 to 5 do
		     (htm "This is test line #" (fmt "~d" i) (:br)))
		   "And this is more text after the LOOP."))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
       NIL
       (WRITE-STRING
	"<html><head><title>A small test page</title></head><body><h1>Test Page</h1>"
	*STANDARD-OUTPUT*)
       (LOOP FOR I FROM 1 TO 5 DO
	 (PROGN
	  (WRITE-STRING "This is test line #" *STANDARD-OUTPUT*)
	  (FORMAT *STANDARD-OUTPUT* "~d" I)
	  (WRITE-STRING "<br />" *STANDARD-OUTPUT*)))
       (WRITE-STRING "And this is more text after the LOOP.</body></html>"
		     *STANDARD-OUTPUT*)))
    T
    >

Does this clarify the issue somewhat?  [If so, feel free to stop here.]

If not, I'll elaborate an example from my previous reply:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue nil)
          (:html
	    (:head (:title "A small test page"))
	    (:body
	      (:h1 "Test Page")
	      (:foo "A FOO with " (:bar "a sample BAR") " in it")))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
       NIL
       (WRITE-STRING
	"<html><head><title>A small test page</title></head><body><h1>Test Page</h1><foo>A FOO with <bar>a sample BAR</bar> in it</foo></body></html>"
	*STANDARD-OUTPUT*)))
    T
    >

O.k.? Nothing special about ":FOO", it's just another keyword that
gets transformed into matching starting & ending tag strings.

But when you replace it with a *non*-keyword, then CL-WHO correctly
just passes it through [as it is documented to], on the assumption
that it is Lisp code that you want to execute:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue nil)
          (:html
	    (:head (:title "A small test page"))
	    (:body
	      (:h1 "Test Page")
	      ((intern "FOO" :keyword)
	       "A FOO with " (:bar "a sample BAR") " in it")))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
       NIL
       (WRITE-STRING
	"<html><head><title>A small test page</title></head><body><h1>Test Page</h1>"
	*STANDARD-OUTPUT*)
        ((INTERN "FOO" :KEYWORD) "A FOO with " (:BAR "a sample BAR") " in it")
       (WRITE-STRING "</body></html>" *STANDARD-OUTPUT*)))
    T
    >

Now ask yourself what's going to happen when the CL system tries
to evaluate that ((INTERN "FOO" :KEYWORD) "A FOO with " ...) form.
*Ka-BLOOEY!*   [CMUCL calls it "Error: Illegal function call."]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <p2LQg.61$e05.28@newsfe09.lga>
Rob Warnock wrote:
> Ken Tilton  <·········@gmail.com> wrote:

> +---------------
> | If not, I would uncross my fingers so I can use the keyboard
> | to hack a CALL-WITH-HTML-OUTPUT out of WITH-HTML-OUTPUT.
> +---------------
> 
> Go back and look at my suggestion *not* to call TREE-TO-COMMANDS
> directly:
> 
>       +--- The really ugly bit.
>       |
>       V
>     (eval (cl-who::tree-to-commands (replace-tags-with-keywords my-tree)
>                                     *standard-output*
>                                     cl-who::*prologue*))
> 
> Given that MY-TREE is generated at *run-time* from reading an XML
> document [he mentioned a purchase order -- presumably all possible
> purchase orders are not known at compile time], do you really want
> him to be calling EVAL there, at run-time? ...when a simple tree-walk
> of MY-TREE could output the desired text *without* any use of EVAL?

Sorry, this is the bit I should have read. You are right, cl-who is 
designed from the ground up not to do anything interesting (at all?) at 
runtime. Or is that (or that?) overstating it?

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <S8Wdndnvlc0ICY7YnZ2dnUVZ_vSdnZ2d@speakeasy.net>
Ken Tilton  <·········@gmail.com> wrote:
+---------------
| Rob Warnock wrote:
| >   *--- The really ugly bit.
| > (eval (cl-who::tree-to-commands (replace-tags-with-keywords my-tree) ...)
...
| Sorry, this is the bit I should have read. You are right, cl-who is 
| designed from the ground up not to do anything interesting (at all?)
| at runtime. Or is that (or that?) overstating it?
+---------------

Well, no... but it's a somewhat "glass half-empty" way of saying it.
I would instead note that "nothing interesting at runtime" is a *good*
thing, since it's just that much more runtime *saved* for real work.  ;-}

Or even better, say that CL-WHO and HTOUT (& friends) were designed
with Common Lisp compilation in mind, and work hard to do as much
as possible at compile time [and at macroexpansion time even before
that] so that they have as little as possible to do at runtime.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <NzSQg.978$Pr4.947@newsfe10.lga>
Rob Warnock wrote:
> Ken Tilton  <·········@gmail.com> wrote:
> +---------------
> | Rob Warnock wrote:
> | >   *--- The really ugly bit.
> | > (eval (cl-who::tree-to-commands (replace-tags-with-keywords my-tree) ...)
> ...
> | Sorry, this is the bit I should have read. You are right, cl-who is 
> | designed from the ground up not to do anything interesting (at all?)
> | at runtime. Or is that (or that?) overstating it?
> +---------------
> 
> Well, no... but it's a somewhat "glass half-empty" way of saying it.
> I would instead note that "nothing interesting at runtime" is a *good*
> thing, since it's just that much more runtime *saved* for real work.  ;-}

Given the power of today's systems and the throughput of broadband, that 
is somewhat a "making lemonade out of lemons" way of viewing it. :)

Looks like it's time for flash-ci.

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Christophe Rhodes
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <sq1wq58ism.fsf@cam.ac.uk>
····@rpw3.org (Rob Warnock) writes:

> [...]
> Since a list that begins with a keyword is not legal CL source code

Yes it is.  (That's not to say that using this as a syntactic marker
for CL-WHO's purposes is a bad idea, but that this can't be the
justification for it.)

> [...]

Christophe
From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <uZOdncLMH-WxDI_YnZ2dnUVZ_qOdnZ2d@speakeasy.net>
Christophe Rhodes  <·····@cam.ac.uk> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > Since a list that begins with a keyword is not legal CL source code
| 
| Yes it is.  (That's not to say that using this as a syntactic marker
| for CL-WHO's purposes is a bad idea, but that this can't be the
| justification for it.)
+---------------

O.k., so I was assuming that somebody hadn't done something
incredibly grotesque like this:

    > (setf (symbol-function :plus) #'+)

    #<Function + {101E4269}>
    > (:plus 3 4 5)

    12
    > 

*NORMALLY*, if you write (:plus 3 4 5), the system will barf.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ken Tilton
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <bVyQg.3$Pr4.2@newsfe10.lga>
Rob Warnock wrote:
> Christophe Rhodes  <·····@cam.ac.uk> wrote:
> +---------------
> | ····@rpw3.org (Rob Warnock) writes:
> | > Since a list that begins with a keyword is not legal CL source code
> | 
> | Yes it is.  (That's not to say that using this as a syntactic marker
> | for CL-WHO's purposes is a bad idea, but that this can't be the
> | justification for it.)
> +---------------
> 
> O.k., so I was assuming that somebody hadn't done something
> incredibly grotesque like this:
> 
>     > (setf (symbol-function :plus) #'+)

Or this:

(defun :grotesque () 'not!!)

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: a
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <nUwQg.4865$lq.132@newsread1.mlpsca01.us.to.verio.net>
"Dustin Withers" <·········@gmail.com> wrote in message
...
> (cl-who:with-html-output (*standard-output* nil :prologue t)
>   ((intern "FOO" :keyword) (:body "test")))
...
> Instead it returns:
> ; in: LAMBDA NIL
> ;     ((INTERN "FOO" :KEYWORD) (:BODY "test"))
> ;
> ; caught ERROR:
...
> Sorry for my ignorance but can anyone explain where my thinking is
> wrong?  I'd like to produce an XML document of the data that I have.
...

(cl-who:with-html-output (*standard-output* nil :prologue t)
   `(,(intern "FOO" :keyword) (:body "test")))

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
(:FOO (:BODY "test"))

Generally, cl-who looks for alternating keyword-data pairs. (intern "FOO" 
:keyword) is not a keyword until after it is evalutated. with-html-output is 
a macro and parameters to macros are not evaluated. The backquote / comma 
syntax can be used in the parameters to force the evaluation before cl-who 
sees the parameters.
From: Dustin Withers
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <1158867676.743444.83490@m7g2000cwm.googlegroups.com>
a wrote:
> (cl-who:with-html-output (*standard-output* nil :prologue t)
>    `(,(intern "FOO" :keyword) (:body "test")))
>
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
> (:FOO (:BODY "test"))

Ok so that works but reading all the responses has made me rethink my
implementation.  For one I need to rework the the parsing of the data
file into a tree.  And then take that tree and turn it into XML.
Thanks for all the info I'll probably have more questions.  If I get
something that can parse X12 correctly is anyone interested?

-dustin
From: Rob Warnock
Subject: Re: Keywords and CL-WHO
Date: 
Message-ID: <kqqdnTkoOdzh7Y7YnZ2dnUVZ_q6dnZ2d@speakeasy.net>
Dustin Withers <·········@gmail.com> wrote:
+---------------
| a wrote:
| > (cl-who:with-html-output (*standard-output* nil :prologue t)
| >    `(,(intern "FOO" :keyword) (:body "test")))
| >
| > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
| > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
| > (:FOO (:BODY "test"))
| 
| Ok so that works...
+---------------

No it doesn't, sorry. "A" confused himself [and you]:

1. The *only* output which went to *STANDARD-OUTPUT* was the prologue.
   None of the FOO stuff went anywhere.

2. WITH-HTML-OUTPUT returns a *value* [which the REPL printed], which
   in the above case happened to be the value of the last form in the
   &BODY arg. The (:FOO (:BODY "test")) value shown above is the result
   of the *evaluation* of the backquoted form, which had no side-effects,
   and in particular was *NOT* output to *STANDARD-OUTPUT*.

The following may make it more clear: First, note that we can replace
the backquoted form by its exact [except for potential sharing of
structure] equivalent expansion:

    > `(,(intern "FOO" :keyword) (:body "test"))

    (:FOO (:BODY "test"))
    > (list (intern "FOO" :keyword) '(:body "test"))

    (:FOO (:BODY "test"))
    > (equal * **)		; See? They're equal.

    T
    > 

Now let's put that version into a sexp-based HTML template
and look at the code that WITH-HTML-OUTPUT generates:

    > (macroexpand
       '(cl-who:with-html-output (*standard-output* nil :prologue t)
	  (:html
	    (:body
	      "Some text"
	      (list (intern "FOO" :keyword) '(:body "test"))
	      "Some more text"))))

    (LET ((*STANDARD-OUTPUT* *STANDARD-OUTPUT*))
      (PROGN
       (WRITE-STRING
	"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html><body>Some text"
	*STANDARD-OUTPUT*)
       (LIST (INTERN "FOO" :KEYWORD) '(:BODY "test"))
       (WRITE-STRING "Some more text</body></html>" *STANDARD-OUTPUT*)))
    T
    > 

See? The LIST form (or the equivalent backquoted form) results in
*only* a value -- the list (:FOO (:BODY "test")) -- which is then
immediately thrown away [since it's not the last such value].
It has no effect on the output:

    > (with-output-to-string (string)
	(cl-who:with-html-output (*standard-output* string :prologue t)
	  (:html
	    (:body
	      "Some text"
	      (list (intern "FOO" :keyword) '(:body "test"))
	      "Some more text"))))

    "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html><body>Some textSome more text</body></html>"
    > 

I again strongly suggest that you consider simply walking your
internal XML document tree yourself, emitting XML (or HTML) text
as needed during the walk. Something like this, but you'd need
to add all the specific details appropriate to your application:

    > (defun walk-and-emit (tree &key (stream *standard-output*))
	(cond
	  ((null tree)
	   nil)
	  ((and (consp tree) (consp (car tree)))
	   (error "This version can't handle attributes: ~s" tree))
	  ((consp tree)
	   (format stream "<~a>" (car tree))
	   (dolist (i (cdr tree))
	     (walk-and-emit i :stream stream))
	   (format stream "</~a>" (car tree)))
	  (t (format stream "~a" tree))))

    WALK-AND-EMIT
    > (with-output-to-string (string)
	(walk-and-emit '(document (type "Purchase Order")
				  (item
				    (description "Desk")
				    (quantity 1)
				    (unit_cost "$153.24"))
				  (item
				    (description "Pencil")
				    (quantity 125)
				    (unit_cost "$0.153")))
		       :stream string))

    "<DOCUMENT><TYPE>Purchase Order</TYPE><ITEM><DESCRIPTION>Desk</DESCRIPTION><QUANTITY>1</QUANTITY><UNIT_COST>$153.24</UNIT_COST></ITEM><ITEM><DESCRIPTION>Pencil</DESCRIPTION><QUANTITY>125</QUANTITY><UNIT_COST>$0.153</UNIT_COST></ITEM></DOCUMENT>"
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607