From: Adam Warner
Subject: &optional with &key
Date: 
Message-ID: <pan.2002.12.10.07.45.09.460703@consulting.net.nz>
Hi all,

Before I knew about &key I was using &rest to parse keyword parameters.
I could parse a URI in these three forms:

   1. (a :href "uri")
   2. (a :href "uri" "description")
   3. (a "description" :href "uri")

I simply returned all keyword-value pairs in one list and non-keyword
arguments in another for processing.

I've now got many in the second form because I converted the URIs
automatically from the HTML syntax <a href="uri">description</a>.

While duplicating the second form using inbuilt Lisp functionality doesn't
appear possible (an &optional after &key is misplaced), I can't even work
out how to specify the first and third forms without using &rest and
parsing the input myself.

This doesn't work...

   (defun a (&optional desc &key href) (write desc) (write href))

...because desc can't be omitted when :href is specified (it leads to the
error "Function called with odd number of keyword arguments.")

I'd like to know how far I can go to provide such variation in input
without having to resort to using &rest and then parsing the resulting
list myself.

Thanks,
Adam

From: Rob Warnock
Subject: Re: &optional with &key
Date: 
Message-ID: <LwednR6YY80OT2igXTWc3A@giganews.com>
Adam Warner <······@consulting.net.nz> wrote:
+---------------
| Before I knew about &key I was using &rest to parse keyword parameters.
| I could parse a URI in these three forms:
|    1. (a :href "uri")
|    2. (a :href "uri" "description")
|    3. (a "description" :href "uri")
...
| This doesn't work...
|    (defun a (&optional desc &key href) (write desc) (write href))
...
| I'd like to know how far I can go to provide such variation in input
| without having to resort to using &rest and then parsing the resulting
| list myself.
+---------------

If you can make one massive search & replace edit over your corpus
and replace all occurences of #2 & #3 with the following alternatives,
life might become a lot simpler for you:

     2'. (a :href "uri" :text "description")
     3'. (a :text "description" :href "uri")


-Rob

p.s. I replied only because I've been using Tim Bradshaw's HTOUT macro
a lot recently, and he similarly finesses the inverse problem -- what to
do about an HTML attribute that has no value. His solution: Force the Lisp
keyword to be provided an explicit value of NIL in that case, e.g.:

     ((:ul :compact nil)	; outputs <UL COMPACT>
       :li "First item."
       :li "Second item.")

p.p.s. In HTOUT, one writes #2 as:

     ((:a :href "uri") "description")

which is yet another solution that works.

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://www.rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Tim Bradshaw
Subject: Re: &optional with &key
Date: 
Message-ID: <ey3vg22uk28.fsf@cley.com>
* Rob Warnock wrote:
> p.s. I replied only because I've been using Tim Bradshaw's HTOUT macro
> a lot recently, and he similarly finesses the inverse problem -- what to
> do about an HTML attribute that has no value. His solution: Force the Lisp
> keyword to be provided an explicit value of NIL in that case, e.g.:

>      ((:ul :compact nil)	; outputs <UL COMPACT>
>        :li "First item."
>        :li "Second item.")

I'd forgotten that, but it seems like a good approach to me (well, it
would...).

> p.p.s. In HTOUT, one writes #2 as:

>      ((:a :href "uri") "description")

> which is yet another solution that works.

I use this notation for the public HTOUT because it makes the common
no-attribute case easy to type, and HTOUT was designed (well, evolved)
in the expectation that people would be typing a fair amount of
lisp-format HTML (indeed, I wrote a whole lisp course in this format -
it's easier to type than real HTML even with all the strings...).  In
the case where the sexp representation is being machine-generated, I
now (in a not-yet-public descendent of HTOUT) use a notation like:

    (tag attributes &rest body)

where attributes is a keyword attribute list.  So:

    (a (:href "foo") "bar")

The disadvantage of this for stuff where you want to really type a lot
of lispy HTML is that you have a lot of (:p () ...) type stuff.  The
advantage is that it's much more Lispy - the car of the form is the
`function' which does the work (and indeed, there are `macros' which
do transformation on this representation, so:

    (tocify (...)
      (h1 () ...)
      ...)

does what you might expect.

--tim