From: Marco Baringer
Subject: Re: macro-biology
Date: 
Message-ID: <m28yfs1rnn.fsf@bese.it>
David Steuber <·····@david-steuber.com> writes:

> First question.  Can a macro only expand into code?  Or can I define a
> macro that will expand into XML for printing?  This expansion may be
> into a string that I pass to format.  The mechanism isn't as important
> as the ability to do so.  Here are a couple examples in pseudolisp
> with the output after printing as with princ or format:

a macro can only expand into code, that code will be eval'd. end of
the story (caveat: this assumes you asked lisp to eval the macro form,
if you're just passing a list to macroexpand things are different).

> (xmlify foo :attr1 "string" :attr2 42) =>
> <foo attr1="string" attr2=42/>
>
> (xmlify bar :attr 42 :baz (all your base)) =>
> <bar attr=42>
>   <baz>all</baz>
>   <baz>your</baz>
>   <baz>base</baz>
> </bar>

so you want xmlify to expand into a string? or do you want xmlify to
expand into a form which prints a string? since strings are
self-evaluating common lisp forms both are doable. of course
expanding directly into a, single, string means you can't do things
like this:

(let ((attr "something"))
  (xmlify foo :attr1 attr)) ==>
<foo attr1='something'/>

> I'm also making the grand assumption that I can nest macros like this:
>
> (xmlify abar :attr "blue" (xmlify prop1 :attr1 69 attr2 foo)) =>
> <abar attr="blue">
>   <prop1 attr1=69 attr2="foo"/>
> </abar>

well, that depends on what the definition of xmlify is. for functions
all the args are evaluated and their return value is passed to the
function, for macros this not the case, the source code is passed to
the macro as is, and whatever the macro returns is evaluated, if the
macro does not enusre that the args get evaluated then, well, they
won't get evaluated (or macro expanded).

> I'm sorry I don't have a more complete specification yet.  Is there a
> better alternative to the above?

just about any of the xml/html/xhtml generating libraries do what you
(seem) to want, and they generally do it by having macrso which expand
into a series of print forms. this allows the "final" result to be
affected by the runtime enviroment, which is very usefull indeed.

> The second question gets a little hairy.  I know that macro expansion
> happens at compile time.  However, I want to have an alternate
> definition of xmlify in the above examples.  The alternate would take
> the exact same stuff, but generate some sort of lisp instead.  The
> same examples, again in psuedolisp:
>
> (xmlify foo :attr1 "string" :attr2 42) =>
> (defparameter foo '(:attr1 "string" :attr2 42))
>
> (xmlify bar :attr 42 :baz (all your base)) =>
> (defparameter bar '(:attr 42 :baz (all your base)))
>
> To deal with the fact that macros happen at compile time, I will only
> use one of the definitions of xmlify at a time.  One for when I want
> to take a file that I want to turn into XML and the other for use in
> Lisp.  The latter version looks like it is trivial to implement.  So
> question no. 1 is the more important of the two.  However the macro
> arguments will need to be the same for both.

why do you think generating lisp is any easier/harder than generating
strings?

> My requirements as far as I know them are to have fairly easy to edit
> rules files that are really just lisp.  However for political reasons,
> those rules also need to be transformable to XML for use in an
> identical application written in another language after being
> prototyped in lisp.  Although I don't plan to throw away the lisp
> version.  I'll probably maintain both lisp and java versions that get
> the rules from the same source files.  Actually, I'll leave it to a
> friend to deal with the Java version ;-)

oh, so you have files with lisp s-exprs which you want to use to
generate xml? why didn't you just say so? :)

just grab one of the many html generating libraries
(http://www.cliki.net/Web) and see what you like best. except for your
:baz (all your base) example they all already do what you want.

<shameless-plug>

yaclml would allow you to do something along these lines:

(deftag bar (&attribute attr baz)
  (wrap-in-tag ("bar" "attr" attr)
    (dolist (b baz)
      (wrap-in-tag ("baz")
        (emit-html (string-downcase b))))))

and here's the macroexpansion of (bar :attr 42 :baz (all your base))

(PROGN (WRITE-STRING "<bar attr=\"42\"><baz>all</baz><baz>your</baz><baz>base</baz></bar>"
                     *YACLML-STREAM*))

a patch to generate readable html output would be greatly appreciated.

</shameless-plug>

> A rules file may look something like this:
>
> (in-package :foo) ; ignored when genning XML
> (xmlify rule1 :attr1 "string" :attr2 42)
> (xmlify rule2 ...)
> ...

since this seems like a pretty custom applicion you could skip the
in-package and manually bind *package* to what you need before
loading.

by using the #\< and #\> as dispatching read macros (and mess with #\=
while you're at it) you may even come up with a syntax which is xml
enough to fool most java programmers. just be sure to call it XML++,
say you read about it in a blog on javablogs.com and charge 2K a seat
for it. :)

hth.
-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen

From: Ari Johnson
Subject: Re: macro-biology
Date: 
Message-ID: <PjNpc.64914$Fl5.745@okepread04>
Marco Baringer wrote:

> by using the #\< and #\> as dispatching read macros (and mess with #\=
> while you're at it) you may even come up with a syntax which is xml
> enough to fool most java programmers. just be sure to call it XML++,
> say you read about it in a blog on javablogs.com and charge 2K a seat
> for it. :)

The name XML++ is taken already, sorry.  How about SXML (has a s-expr 
ring to it)? :)
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87r7tjvpq0.fsf@david-steuber.com>
Ari Johnson <·····@hotmail.com> writes:

> Marco Baringer wrote:
> 
> > by using the #\< and #\> as dispatching read macros (and mess with #\=
> > while you're at it) you may even come up with a syntax which is xml
> > enough to fool most java programmers. just be sure to call it XML++,
> > say you read about it in a blog on javablogs.com and charge 2K a seat
> > for it. :)
> 
> The name XML++ is taken already, sorry.  How about SXML (has a s-expr
> ring to it)? :)

Or SeXML for more appeal?

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Rob Warnock
Subject: Re: macro-biology
Date: 
Message-ID: <Mu6dndG-e6yhtDXdRVn-sQ@speakeasy.net>
Ari Johnson  <·····@hotmail.com> wrote:
+---------------
| Marco Baringer wrote:
| > ... just be sure to call it XML++,
| 
| The name XML++ is taken already, sorry.  How about SXML (has a s-expr 
| ring to it)? :)
+---------------

Except there already *is* an SXML (circa 2000), which is the output
format of Oleg Kiselyov's SSAX XML parser, see:

    <URL:http://pobox.com/~oleg/ftp/Scheme/SXML.html>
    <URL:http://pobox.com/~oleg/ftp/Scheme/SSAX.scm>
    <URL:http://pobox.com/~oleg/ftp/Scheme/SXPath.scm>


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Ari Johnson
Subject: Re: macro-biology
Date: 
Message-ID: <HfWpc.164924$f_5.124371@lakeread01>
Rob Warnock wrote:

> Ari Johnson  <·····@hotmail.com> wrote:
> +---------------
> | Marco Baringer wrote:
> | > ... just be sure to call it XML++,
> | 
> | The name XML++ is taken already, sorry.  How about SXML (has a s-expr 
> | ring to it)? :)
> +---------------
> 
> Except there already *is* an SXML (circa 2000), which is the output
> format of Oleg Kiselyov's SSAX XML parser, see:
> 
>     <URL:http://pobox.com/~oleg/ftp/Scheme/SXML.html>
>     <URL:http://pobox.com/~oleg/ftp/Scheme/SSAX.scm>
>     <URL:http://pobox.com/~oleg/ftp/Scheme/SXPath.scm>

Fine, we'll add the 'e' like David suggested. :)
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87u0ygqqhw.fsf@david-steuber.com>
Marco Baringer <··@bese.it> writes:

> David Steuber <·····@david-steuber.com> writes:
> 
> > First question.  Can a macro only expand into code?  Or can I define a
> > macro that will expand into XML for printing?  This expansion may be
> > into a string that I pass to format.  The mechanism isn't as important
> > as the ability to do so.  Here are a couple examples in pseudolisp
> > with the output after printing as with princ or format:
> 
> a macro can only expand into code, that code will be eval'd. end of
> the story (caveat: this assumes you asked lisp to eval the macro form,
> if you're just passing a list to macroexpand things are different).

But that code can be a form that prints a string or just generates a
string or generates several strings and loops through them or ...

> > (xmlify foo :attr1 "string" :attr2 42) =>
> > <foo attr1="string" attr2=42/>
> >
> > (xmlify bar :attr 42 :baz (all your base)) =>
> > <bar attr=42>
> >   <baz>all</baz>
> >   <baz>your</baz>
> >   <baz>base</baz>
> > </bar>
> 
> so you want xmlify to expand into a string? or do you want xmlify to
> expand into a form which prints a string?

The latter I think.  Just a string by itself won't do me much good.  I
would want something that can be sent to a stream.

> > I'm also making the grand assumption that I can nest macros like this:
> >
> > (xmlify abar :attr "blue" (xmlify prop1 :attr1 69 attr2 foo)) =>
> > <abar attr="blue">
> >   <prop1 attr1=69 attr2="foo"/>
> > </abar>
> 
> well, that depends on what the definition of xmlify is. for functions
> all the args are evaluated and their return value is passed to the
> function, for macros this not the case, the source code is passed to
> the macro as is, and whatever the macro returns is evaluated, if the
> macro does not enusre that the args get evaluated then, well, they
> won't get evaluated (or macro expanded).

A form like this is legal:

(loop for i from 1 to 10 do
  (loop for j from 1 to 10 do
    (something with i and j)))

I imagine that to deal with suddenly needing a closing tag means
building up some sort of lexical environment to detect the condition.
Or perhasp there is a better way to handle that case.  If you know
your list is really a tree, I'm sure you can do something with that
information.

> just about any of the xml/html/xhtml generating libraries do what you
> (seem) to want, and they generally do it by having macrso which expand
> into a series of print forms. this allows the "final" result to be
> affected by the runtime enviroment, which is very usefull indeed.

I'll hunt through cliki and common-lisp.net for those.  I don't doubt
there is some way to do it.  I just don't know how hairy the problem
is.

> why do you think generating lisp is any easier/harder than generating
> strings?

Because I think the macro will be simpler.  I may be able to get away
with something not much more complicated than this (untested off the
cuff probably wrong macro):

(defvar hash (make-hashtable :test '#eq))
(defmacro xmlify (&body) 
  `(setf (gethash (quote (car ,@body)) hash) (cdr ,@body)))

> oh, so you have files with lisp s-exprs which you want to use to
> generate xml? why didn't you just say so? :)

Well, not yet I don't.  But I plan to make some and the format will
depend largely on what I can figure out how to do with macros and
other lisp facilities that aid in solving my problem.

I'm flying by the seat of my pants in IFR conditions here.

> just grab one of the many html generating libraries
> (http://www.cliki.net/Web) and see what you like best. except for your
> :baz (all your base) example they all already do what you want.

They don't handle the :baz case?  Someone must not be sharing ;-)

> yaclml would allow you to do something along these lines:
> 
> (deftag bar (&attribute attr baz)
>   (wrap-in-tag ("bar" "attr" attr)
>     (dolist (b baz)
>       (wrap-in-tag ("baz")
>         (emit-html (string-downcase b))))))
> 
> and here's the macroexpansion of (bar :attr 42 :baz (all your base))
> 
> (PROGN (WRITE-STRING "<bar attr=\"42\"><baz>all</baz><baz>your</baz><baz>base</baz></bar>"
>                      *YACLML-STREAM*))
> 
> a patch to generate readable html output would be greatly appreciated.

If you know you are getting a closing tag, you can insert a \#newline
after it.  If you don't, then I guess it is a little harder.  If you
know about opening and closing tags, then you can use a stack to track
indentation level.  I haven't looked at pretty printing yet, so I
don't know how far off that idea is.  Actually, when I say stack, I
mean a small integer where you increment it for each opening tag and
decrement it for each closing tag.

> > A rules file may look something like this:
> >
> > (in-package :foo) ; ignored when genning XML
> > (xmlify rule1 :attr1 "string" :attr2 42)
> > (xmlify rule2 ...)
> > ...
> 
> since this seems like a pretty custom applicion you could skip the
> in-package and manually bind *package* to what you need before
> loading.

I don't know how to do that.  For some reason, most Lisp books
consider packages an advanced topic.  I only know about in-package and
a (very) few other things thanks to ASDF.  As it is, I haven't written
any macros yet, save the one in this post.  Since it isn't tested, it
doesn't count.

> by using the #\< and #\> as dispatching read macros (and mess with #\=
> while you're at it) you may even come up with a syntax which is xml
> enough to fool most java programmers. just be sure to call it XML++,
> say you read about it in a blog on javablogs.com and charge 2K a seat
> for it. :)

Heh.  Now wouldn't that be something?  I don't think I'm ready to
tackle messing with the read table yet.  But certainly anyone willing
to pay 2K per seat for text should be throwing some money my way.

As you have observed, this is a custom app.  So far, the number of
interested users is solidly in unity.  If I am lucky, I might be able
to double the number to two.  That's when I will need to do XML.  If
the number of users grows beyond two, then maybe I can contact Hasbro
and offer to sell it.

Of course, s-expressions are much easier to type than XML.  I expect
that a general s-expression to XML filter would be useful for cases
where it is easier to type it all into a text editor rather than use
some specialized tool for genning XML from forms or whatnot.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Marco Baringer
Subject: Re: macro-biology
Date: 
Message-ID: <m2fz9xg9to.fsf@bese.it>
David Steuber <·····@david-steuber.com> writes:

>> so you want xmlify to expand into a string? or do you want xmlify to
>> expand into a form which prints a string?
>
> The latter I think.  Just a string by itself won't do me much good.  I
> would want something that can be sent to a stream.

just to be precise, you'd want something that, when eval'd, sends
something to a string.

>> well, that depends on what the definition of xmlify is. for functions
>> all the args are evaluated and their return value is passed to the
>> function, for macros this not the case, the source code is passed to
>> the macro as is, and whatever the macro returns is evaluated, if the
>> macro does not enusre that the args get evaluated then, well, they
>> won't get evaluated (or macro expanded).
>
> A form like this is legal:
>
> (loop for i from 1 to 10 do
>   (loop for j from 1 to 10 do
>     (something with i and j)))

sorry, what should this produce?

>> oh, so you have files with lisp s-exprs which you want to use to
>> generate xml? why didn't you just say so? :)
>
> Well, not yet I don't.  But I plan to make some and the format will
> depend largely on what I can figure out how to do with macros and
> other lisp facilities that aid in solving my problem.
>
> I'm flying by the seat of my pants in IFR conditions here.

what's "IFR"? Google turned up "Instrument Flight Rules", but i don't
think that's what you meant.

>> just grab one of the many html generating libraries
>> (http://www.cliki.net/Web) and see what you like best. except for your
>> :baz (all your base) example they all already do what you want.
>
> They don't handle the :baz case?  Someone must not be sharing ;-)

you seem to want to pass a list as the value of an attribute and have
that generate not a tag attribute but a set of nested tags, this
isn't (afaict) a normal use of tag attributes. this is how i would
expect your example to be expressed:

(xmlify bar :attr 42
  (xmlify baz 'all)
  (xmlify baz 'your)
  (xmlify baz 'base))

after a while you'll get tired of typing xmlify all the time and
you'll just make bar and baz be macros.

> If you know you are getting a closing tag, you can insert a \#newline
> after it.  If you don't, then I guess it is a little harder.  If you
> know about opening and closing tags, then you can use a stack to track
> indentation level.  I haven't looked at pretty printing yet, so I
> don't know how far off that idea is.  Actually, when I say stack, I
> mean a small integer where you increment it for each opening tag and
> decrement it for each closing tag.

unfortunetly that is not the case when generating html. in particular
if you have something like this:

(p "this is in " (i "italics") ".")

if you put a trailing newline after the </i> generated by (i
"italics") you get a space between the end of the word 'italics' and
the trailing '.' (in some browsers). so you'd have to distinugiush
between inline tags and block tags, something i've never bothered to
sit down and do.

> I don't know how to do that.  For some reason, most Lisp books
> consider packages an advanced topic.  I only know about in-package and
> a (very) few other things thanks to ASDF.  As it is, I haven't written
> any macros yet, save the one in this post.  Since it isn't tested, it
> doesn't count.

(let ((*package* (find-package :config-file-package)))
  (load "config-file"))

> Of course, s-expressions are much easier to type than XML.  I expect
> that a general s-expression to XML filter would be useful for cases
> where it is easier to type it all into a text editor rather than use
> some specialized tool for genning XML from forms or whatnot.

don't forget the power of C-M-t, C-M-SPC, C-M-f, etc. i can't believe
XML editors haven't adopted these yet. 

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen
From: Peter Seibel
Subject: Re: macro-biology
Date: 
Message-ID: <m3ekphsmdi.fsf@javamonkey.com>
Marco Baringer <··@bese.it> writes:

> David Steuber <·····@david-steuber.com> writes:
>
>> I'm flying by the seat of my pants in IFR conditions here.
>
> what's "IFR"? Google turned up "Instrument Flight Rules", but i
> don't think that's what you meant.

No that's right. "IFR conditions" would be flying conditions where the
pilot must be able to fly based only on the readings of their
instruments, without looking out the window (such as when there's
thick fog and nothing to see out the window anyway). As opposed to
Visual Flight Rules (VFR). (Beginning pilots are only licensed for VFR
conditions so can only fly on clear days.)

So he's flying "by the seat of [his] pants" (i.e. without instruments)
in conditions that require instruments.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Rob Warnock
Subject: Re: macro-biology
Date: 
Message-ID: <RqidnfyWBsXqzjbd4p2dnA@speakeasy.net>
Peter Seibel  <·····@javamonkey.com> wrote:
+---------------
| > David Steuber <·····@david-steuber.com> writes:
| >> I'm flying by the seat of my pants in IFR conditions here.
...
| So he's flying "by the seat of [his] pants" (i.e. without instruments)
| in conditions that require instruments.
+---------------

And what's really dangerous about *that* is that it's well-known
[at least, to IFR-trained pilots!] that the seat of one's pants is
a very unreliable indicator of attitude in some cases, e.g., the
so-called "graveyard spiral" in which one *feels* as if one is flying
straight & level [because perceived "down" remains pointing straight
down at the floor of the cabin] while in fact the aircraft is spiralling
increasingly-steeply into the ground. (Oops.)


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <871xleij6t.fsf@david-steuber.com>
····@rpw3.org (Rob Warnock) writes:

> Peter Seibel  <·····@javamonkey.com> wrote:
> +---------------
> | > David Steuber <·····@david-steuber.com> writes:
> | >> I'm flying by the seat of my pants in IFR conditions here.
> ...
> | So he's flying "by the seat of [his] pants" (i.e. without instruments)
> | in conditions that require instruments.
> +---------------
> 
> And what's really dangerous about *that* is that it's well-known
> [at least, to IFR-trained pilots!] that the seat of one's pants is
> a very unreliable indicator of attitude in some cases, e.g., the
> so-called "graveyard spiral" in which one *feels* as if one is flying
> straight & level [because perceived "down" remains pointing straight
> down at the floor of the cabin] while in fact the aircraft is spiralling
> increasingly-steeply into the ground. (Oops.)

Drifting off topic for a bit...

Yes indeed.  And by definition, in IFR conditions you have no visible
horizon to rely upon.  You MUST use the artificial horizon in the
center of your display.  Of course, if that isn't working, an IFR
rated pilot should be able to tell that something is amis from the
heading indicator, airspeed, etc all acting as they would as you
tighten your spiral into a spin.  Hopefully you figure that out before
JFK jr did (who wasn't IFR rated).

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Christopher C. Stacy
Subject: IFR [was: macro-biology]
Date: 
Message-ID: <ulljmtq2v.fsf_-_@news.dtpq.com>
>>>>> On 20 May 2004 22:54:18 -0400, David Steuber ("David") writes:

 David> ····@rpw3.org (Rob Warnock) writes:
 >> Peter Seibel  <·····@javamonkey.com> wrote:
 >> +---------------
 >> | > David Steuber <·····@david-steuber.com> writes:
 >> | >> I'm flying by the seat of my pants in IFR conditions here.
 >> ...
 >> | So he's flying "by the seat of [his] pants" (i.e. without instruments)
 >> | in conditions that require instruments.
 >> +---------------
 >> 
 >> And what's really dangerous about *that* is that it's well-known
 >> [at least, to IFR-trained pilots!] that the seat of one's pants is
 >> a very unreliable indicator of attitude in some cases, e.g., the
 >> so-called "graveyard spiral" in which one *feels* as if one is flying
 >> straight & level [because perceived "down" remains pointing straight
 >> down at the floor of the cabin] while in fact the aircraft is spiralling
 >> increasingly-steeply into the ground. (Oops.)

 David> Drifting off topic for a bit...

 David> Yes indeed.  And by definition, in IFR conditions you have no visible
 David> horizon to rely upon.  You MUST use the artificial horizon in the
 David> center of your display.  Of course, if that isn't working, an IFR
 David> rated pilot should be able to tell that something is amis from the
 David> heading indicator, airspeed, etc all acting as they would as you
 David> tighten your spiral into a spin.  Hopefully you figure that out before
 David> JFK jr did (who wasn't IFR rated).

Just a nitpick: instrument meteorological conditions (IMC) imply 
that you should be flying under Instrument Flight Rules (IFR).
However, there are other "IFR conditions" (I don't think that's 
a formally defined phrase).  If you are in the Positive Control
Airspace, for example, you are required to be flying IFR, even 
though it may be perfectly clear and you can see the surface 
and for hundreds of miles out.

Flying on a partially functioning instrument panel is extremely taxing, 
and represents a serious emergency situation.  This is one reason why 
in addition to all the duplicate sets of instruments, including a third
redundant self-powered attitude indicator -- so that you don't ever have
fly without an artificial horizon -- passenger airlines also feature 
redundant pilots.  Single-pilot partial-panel IFR is something that
instrument-rated pilots train for, but pulling it off successfully 
in real live and (by definition) unexpected conditions is not easy.

In the case of JFK Jr., he was not even instrument rated.  
He was under artificial pressure to make the trip (for a wedding), 
was carrying passengers (eg. sitting in the cockpit next to him),
and (due to his poor planning) "unexpectedly" encountered IMC
conditions, at night, that he apparently figured he could handle.
(I bet he didn't even realize that he was in IMC until he was out
of control; that's how it usually goes. An unexpected transition 
from visual to instrument conditions is often momentarily confusing 
even for instrument-rated pilots.) The resulting deaths were
textbook predictable.  The government's extraordinary recovery
efforts were nothing like what happens when regular people crash 
in exactly the same way.

I dunno how we got on this rant, though.
From: David Steuber
Subject: Re: IFR [was: macro-biology]
Date: 
Message-ID: <87y8nm8f8s.fsf@david-steuber.com>
······@news.dtpq.com (Christopher C. Stacy) writes:

> >>>>> On 20 May 2004 22:54:18 -0400, David Steuber ("David") writes:
> 
>  >> | >> I'm flying by the seat of my pants in IFR conditions here.
>
> I dunno how we got on this rant, though.

Heh.  Yeah.  I can trace it back to the above quoted text.  Although
for a full causality analysis, we need a grand unification theory that
explains the big bang.

I'm rather out of date with my FAR/AIM stuff.  Flying is an expensive
hobby that I fell out of a long time back but I still once in a while
use it in metephors.

Perhaps I should have just said I was programming with incomplete
specifications, but that's pretty much the industry norm.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87u0ydt48a.fsf@david-steuber.com>
Marco Baringer <··@bese.it> writes:

> David Steuber <·····@david-steuber.com> writes:
> > I'm flying by the seat of my pants in IFR conditions here.
> 
> what's "IFR"? Google turned up "Instrument Flight Rules", but i don't
> think that's what you meant.

Actually, that is exactly what I meant.  And that is also what killed
JKF jr.

I'm working on a macro to produce Lisp.  I have been strugling quite a
bit with it.  I'm sure I am falling into all the pits that a beginner
falls into and then some.  What I have right now is fairly ugly and
incomplete.  I have an unimplemented keyword argument that SBCL keeps
warning me about that is supposed to allow me to produce a bunch of
similar lisp forms rather than just one.  Here is what I have right
now:

(defstruct skill 
  name
  key-ability
  (trained-only nil)
  (armor-check-penalty nil)
  (check nil)
  (action nil)
  (try-again nil)
  (special nil)
  (synergy nil)
  (restriction nil)
  (untrained nil))

(defmacro skill (&key symbol name key-ability
                 subskill trained-only armor-check-penalty
                 check action try-again special synergy
                 restriction untrained)
  "Create skills based on the skill structure"
  (macrolet ((k (k v) `(when ,v ,k))
             (v (v) `(when ,v ,v)))
    (flet ((s () `(defparameter ,symbol (make-skill :name ,name :key-ability ,key-ability
                                                    ,(k :trained-only trained-only) ',(v trained-only)
                                                    ,(k :armor-check-penalty armor-check-penalty) ',(v armor-check-penalty)
                                                    ,(k :check check) ',(v check)
                                                    ,(k :action action) ',(v action)
                                                    ,(k :try-again try-again) ',(v try-again)
                                                    ,(k :special special) ',(v special)
                                                    ,(k :synergy synergy) ',(v synergy)
                                                    ,(k :restriction restriction) ',(v restriction)
                                                    ,(k :untrained untrained) ',(v untrained)))))
      (s))))

(macroexpand-1 '(skill :symbol apraise :name "Apraise" :key-ability :int :try-again t :synergy craft :special appraise-special-fn))


The skill macro is intended to make instances of the skill structure.
The unused subskill key is meant to take a plist so that I can make an
instance of a skill for each pair in the list where the list is
(symbol "string" ...).  I haven't figured out how to do that part yet.
The final form I want is symbol-symbol and "name(string)".  I'm
assuming an iteration of some sort will be needed hence the FLET.

The MACROLET is in there because that was the first way I figured out
how to solve a problem I was having getting code outside of a list to
be made on condition of the keys being passed into the macro.  I'm not
really happy with that solution.

The macroexpansion produces a lot of nils.  make-skill doesn't seem to
mind them, but they make me worry that I've done something completely
wrong.  I wanted k & v to expand into nothing, not even nil, when the
value fails the WHEN.

I probably should have started with a WHILE macro, but that has been
done to death.

Can a macro conditionaly expand into nothing?  I tried using (values)
but that didn't do it.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <jWCqc.48908$mX.17993300@twister.nyc.rr.com>
David Steuber wrote:
> Marco Baringer <··@bese.it> writes:
> 
> 
>>David Steuber <·····@david-steuber.com> writes:
>>
>>>I'm flying by the seat of my pants in IFR conditions here.
>>
>>what's "IFR"? Google turned up "Instrument Flight Rules", but i don't
>>think that's what you meant.
> 
> 
> Actually, that is exactly what I meant.  And that is also what killed
> JKF jr.
> 
> I'm working on a macro to produce Lisp.  I have been strugling quite a
> bit with it.  I'm sure I am falling into all the pits that a beginner
> falls into and then some.  What I have right now is fairly ugly and
> incomplete.  I have an unimplemented keyword argument that SBCL keeps
> warning me about that is supposed to allow me to produce a bunch of
> similar lisp forms rather than just one.  Here is what I have right
> now:
> 
> (defstruct skill 
>   name
>   key-ability
>   (trained-only nil)
>   (armor-check-penalty nil)
>   (check nil)
>   (action nil)
>   (try-again nil)
>   (special nil)
>   (synergy nil)
>   (restriction nil)
>   (untrained nil))
> 
> (defmacro skill (&key symbol name key-ability
>                  subskill trained-only armor-check-penalty
>                  check action try-again special synergy
>                  restriction untrained)
>   "Create skills based on the skill structure"
>   (macrolet ((k (k v) `(when ,v ,k))
>              (v (v) `(when ,v ,v)))
>     (flet ((s () `(defparameter ,symbol (make-skill :name ,name :key-ability ,key-ability
>                                                     ,(k :trained-only trained-only) ',(v trained-only)
>                                                     ,(k :armor-check-penalty armor-check-penalty) ',(v armor-check-penalty)
>                                                     ,(k :check check) ',(v check)
>                                                     ,(k :action action) ',(v action)
>                                                     ,(k :try-again try-again) ',(v try-again)
>                                                     ,(k :special special) ',(v special)
>                                                     ,(k :synergy synergy) ',(v synergy)
>                                                     ,(k :restriction restriction) ',(v restriction)
>                                                     ,(k :untrained untrained) ',(v untrained)))))
>       (s))))
> 
> (macroexpand-1 '(skill :symbol apraise :name "Apraise" :key-ability :int :try-again t :synergy craft :special appraise-special-fn))
> 
> 
> The skill macro is intended to make instances of the skill structure.

Is this overkill? I do not see much value added over just coding 
make-skill outright. The user still codes the keywords. when you add a 
structure slot you have to add a macro keyword and extend the hard-coded 
list of ",(k <keyword> ..." forms. All that repetition cries out for a 
Lispier metaprogramming approach. But then I get back to "just use 
make-skill".

I am suspicious of the hidden defparameter; again, I do not see much 
added value in that, but I wonder if that gives you the flexibility you 
need. A recent thread here ended up with the OP being persuaded to use 
hash tables to store such things.

I am not sure how/where the subskills will be stored, so I also am not 
sure if they justify the macro.

As for the nils, you can lose those by losing the V macro and changing K 
to be: (flet ((k (k v) (when v (list k v)))...
and then:   (make-list .... ,@(append (k :bang bang) (k :boom boom))

But why not just (make-list .... :bang ,bang :boom ,boom)? if you do not 
want unsupplied args to the macro shadowing possible future defaults 
with nil, use the trick for losing the nils. But I think this is another 
sign that the macro is too close to make-list and just getting in the way.

hth, kenny



> The unused subskill key is meant to take a plist so that I can make an
> instance of a skill for each pair in the list where the list is
> (symbol "string" ...).  I haven't figured out how to do that part yet.
> The final form I want is symbol-symbol and "name(string)".  I'm
> assuming an iteration of some sort will be needed hence the FLET.
> 
> The MACROLET is in there because that was the first way I figured out
> how to solve a problem I was having getting code outside of a list to
> be made on condition of the keys being passed into the macro.  I'm not
> really happy with that solution.
> 
> The macroexpansion produces a lot of nils.  make-skill doesn't seem to
> mind them, but they make me worry that I've done something completely
> wrong.  I wanted k & v to expand into nothing, not even nil, when the
> value fails the WHEN.
> 
> I probably should have started with a WHILE macro, but that has been
> done to death.
> 
> Can a macro conditionaly expand into nothing?  I tried using (values)
> but that didn't do it.
> 

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87k6z8ddp7.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> > The skill macro is intended to make instances of the skill structure.
> 
> Is this overkill? I do not see much value added over just coding
> make-skill outright. The user still codes the keywords. when you add a
> structure slot you have to add a macro keyword and extend the
> hard-coded list of ",(k <keyword> ..." forms. All that repetition
> cries out for a Lispier metaprogramming approach. But then I get back
> to "just use make-skill".

It is both yes and no.  Yes, I could just do make-skill for each skill
that I want in the code.  No in that I may have need for additional
skills so I would simply have a file of skills (admitedly that is a
weak argument for no).  Also, I want to have a seperate, identically
named macro that would take the skill definitions and produce XML
instead of Lisp.

But don't think that I am not constantly asking myself why the heck
I'm doing this rather than going the direct route.

> I am suspicious of the hidden defparameter; again, I do not see much
> added value in that, but I wonder if that gives you the flexibility
> you need. A recent thread here ended up with the OP being persuaded to
> use hash tables to store such things.

Using a hash table is another option.  In fact, there is a very good
chance that I will go that way.

> As for the nils, you can lose those by losing the V macro and changing
> K to be: (flet ((k (k v) (when v (list k v)))...
> and then:   (make-list .... ,@(append (k :bang bang) (k :boom boom))

Ah!  Well even if I abandon the macro, this is nice to know.  I
should have realized that was part of what ,@ was for (splicing in a
list without the top level parens).

As for subskills, here is an abbreviated example of how that is
intended to be used (unless I change my mind):

(skill craft "Craft" :subskills (foo "Foo" bar "Bar" baz "Baz") ...)

This would then give me:

(defparameter craft-foo (make-skill :name "Craft(Foo)" ...))
(defparameter craft-bar (make-skill :name "Craft(Bar)" ...))
(defparameter craft-baz (make-skill :name "Craft(Baz)" ...))

That isn't implemented yet, so that wasn't obviouse from my
explaination.  Sorry.

Certainly an alternative to using defparameters would be to have forms
inserting each skill into a hashtable.  I haven't decided which way to
go yet, but I am leaning more and more in that direction.  There will
be enough of them for a hashtable to be worthwhile.  Anther nice thing
about a hashtable is not having to muck about building symbols in a
macro.

Also imagine a dozen subskills instead of just three.

I guess the biggest reason for my lack of satisfaction with that macro
is that it is too big!  I end up not saving anything at all typing
wise and have fairly weak syntactic sugar to boot.

Also if it turns out that I could be using a function instead of a
macro, that would likely be a better way to go if one follows the
general rule of only using macros when functions won't do the job or
at least won't do them as succinctly.

The more I think about this the more I think I may be able to just use
a function.  A function can add elements to a hashtable no problem.  I
don't think a function can take unquoted symbols that have no defined
values though.  But I might just drop the whole using symbols thing as
a throwback to the 1960's.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <BLHqc.48910$mX.18041562@twister.nyc.rr.com>
David Steuber wrote:

> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>>The skill macro is intended to make instances of the skill structure.
>>
>>Is this overkill? I do not see much value added over just coding
>>make-skill outright. The user still codes the keywords. when you add a
>>structure slot you have to add a macro keyword and extend the
>>hard-coded list of ",(k <keyword> ..." forms. All that repetition
>>cries out for a Lispier metaprogramming approach. But then I get back
>>to "just use make-skill".
> 
> 
> It is both yes and no.  Yes, I could just do make-skill for each skill
> that I want in the code.  No in that I may have need for additional
> skills so I would simply have a file of skills (admitedly that is a
> weak argument for no).

I do not see how coding make-skill gets in the way of possible future 
needs for additional skills, so I am not sure how to respond other than 
to say I am not suggesting limiting what you can do, just limiting a 
possible unjustified syntactic flourish.


   Also, I want to have a seperate, identically
> named macro that would take the skill definitions and produce XML
> instead of Lisp.

Identically named? OK, so you have these (skill...) forms in a file and 
you change what they expand into by having a different macro definition 
for SKILL in place at...compile-time. ie, these skill files cannot just 
be FASLs? I think this is a mistake. You are moving runtime processing 
into compile time, such that you won't be able to have it both ways 
(skills loaded up in a hashtable and written to XML). ie, there you are 
testing happily away and you want to dump it to XML. Step 1, redefine 
SKILL. Nah.... <g>

> 
> But don't think that I am not constantly asking myself why the heck
> I'm doing this rather than going the direct route.

Ah, yes, that old "there's gotta be a better way" harbinger of rewrites 
to come.

> As for subskills, here is an abbreviated example of how that is
> intended to be used (unless I change my mind):
> 
> (skill craft "Craft" :subskills (foo "Foo" bar "Bar" baz "Baz") ...)
> 
> This would then give me:
> 
> (defparameter craft-foo (make-skill :name "Craft(Foo)" ...))

(Long) Hint: Surely you mean '(craft foo). ie, lose the string 
orientation (using them, concatenating them), use sexprs, and if you are 
stuffing skills in a hash table on the name, does the skill need to 
include its own name as part of the skill? Please note that I am note as 
it might appear critiquing your proposal so much as wondering if it 
could be Lispier.

Another thing: this naming convention suggests to me that subskills are 
owned by their parents. I can see you want to dynamically add subskills 
by simply creating skills with the name (append skill-name (list 
sub-skill-name-extension)). Would it be more flexible to bifurcate the 
skill definition from the insersation-cum-subskill? Let the skill have 
an id (foo or bar or baz), and offer some other syntax for superskill 
specification. Then at load time skills could be pushed onto superskill 
subskill lists and instead of finding subskills by finding skills with 
the same root as myself, I just look to my list of subskills.


> (defparameter craft-bar (make-skill :name "Craft(Bar)" ...))
> (defparameter craft-baz (make-skill :name "Craft(Baz)" ...))
> 
> That isn't implemented yet, so that wasn't obviouse from my
> explaination.  Sorry.
> 
> Certainly an alternative to using defparameters would be to have forms
> inserting each skill into a hashtable.  I haven't decided which way to
> go yet, but I am leaning more and more in that direction.  There will
> be enough of them for a hashtable to be worthwhile.  Anther nice thing
> about a hashtable is not having to muck about building symbols in a
> macro.
> 
> Also imagine a dozen subskills instead of just three.
> 
> I guess the biggest reason for my lack of satisfaction with that macro
> is that it is too big!  I end up not saving anything at all typing
> wise and have fairly weak syntactic sugar to boot.

Yep.

> 
> Also if it turns out that I could be using a function instead of a
> macro, that would likely be a better way to go if one follows the
> general rule of only using macros when functions won't do the job or
> at least won't do them as succinctly.
> 
> The more I think about this the more I think I may be able to just use
> a function.  A function can add elements to a hashtable no problem.  I
> don't think a function can take unquoted symbols that have no defined
> values though.  But I might just drop the whole using symbols thing as
> a throwback to the 1960's.
> 

As you have noted elsewhere, 60s Lisp is still as modern as you wannabe. 
I think the symbols per se are OK, but you yourself are still going thru 
a Lispification so you are kinda using symbols in a half Lisp, half C 
kinda way, using them but also using strings and concatenating 
symbol-name strings into longer-symbols which should simply be lists of 
the symbols.

hth, kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Christopher C. Stacy
Subject: Re: macro-biology
Date: 
Message-ID: <ubrkkflb4.fsf@news.dtpq.com>
>>>>> On Wed, 19 May 2004 11:43:29 GMT, Kenny Tilton ("Kenny") writes:

 Kenny> David Steuber wrote:

 >> Kenny Tilton <·······@nyc.rr.com> writes:
 >> 
 >>>> The skill macro is intended to make instances of the skill structure.
 >>> 
 >>> Is this overkill? I do not see much value added over just coding
 >>> make-skill outright. The user still codes the keywords. when you add a
 >>> structure slot you have to add a macro keyword and extend the
 >>> hard-coded list of ",(k <keyword> ..." forms. All that repetition
 >>> cries out for a Lispier metaprogramming approach. But then I get back
 >>> to "just use make-skill".
 >> It is both yes and no.  Yes, I could just do make-skill for each
 >> skill
 >> that I want in the code.  No in that I may have need for additional
 >> skills so I would simply have a file of skills (admitedly that is a
 >> weak argument for no).

 Kenny> I do not see how coding make-skill gets in the way of possible future
 Kenny> needs for additional skills, so I am not sure how to respond other
 Kenny> than to say I am not suggesting limiting what you can do, just
 Kenny> limiting a possible unjustified syntactic flourish.

It sounds like he's using delarative programming style to define an
abstraction called a "skill".  That's not a purely syntactic issue.
But perhaps he intends the SKILL macro to be used by people who are
not Lisp programmers, and the minor syntax advantage the that macro
provides will be easier for them to handle.
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <bZLqc.48927$mX.18120245@twister.nyc.rr.com>
Christopher C. Stacy wrote:
>>>>>>On Wed, 19 May 2004 11:43:29 GMT, Kenny Tilton ("Kenny") writes:
> 
> 
>  Kenny> David Steuber wrote:
> 
>  >> Kenny Tilton <·······@nyc.rr.com> writes:
>  >> 
>  >>>> The skill macro is intended to make instances of the skill structure.
>  >>> 
>  >>> Is this overkill? I do not see much value added over just coding
>  >>> make-skill outright. The user still codes the keywords. when you add a
>  >>> structure slot you have to add a macro keyword and extend the
>  >>> hard-coded list of ",(k <keyword> ..." forms. All that repetition
>  >>> cries out for a Lispier metaprogramming approach. But then I get back
>  >>> to "just use make-skill".
>  >> It is both yes and no.  Yes, I could just do make-skill for each
>  >> skill
>  >> that I want in the code.  No in that I may have need for additional
>  >> skills so I would simply have a file of skills (admitedly that is a
>  >> weak argument for no).
> 
>  Kenny> I do not see how coding make-skill gets in the way of possible future
>  Kenny> needs for additional skills, so I am not sure how to respond other
>  Kenny> than to say I am not suggesting limiting what you can do, just
>  Kenny> limiting a possible unjustified syntactic flourish.
> 
> It sounds like he's using delarative programming style to define an
> abstraction called a "skill".  That's not a purely syntactic issue.
> But perhaps he intends the SKILL macro to be used by people who are
> not Lisp programmers, and the minor syntax advantage the that macro
> provides will be easier for them to handle.

(a) yep, I am just fishing.

(b) i would still or even more so expect a language presented to users 
to diverge further from the implementing Lisp. But then he is just 
getting started on this thing and often the ideas for "value added" 
accrue over time. But I do not start on a macro until they are 
motivated, so I can know how to write the macro rather than guess at 
what it should look like in anticipation of future growth. But mileage 
differs. :)

kenny

Ps. Note to OP re "SBCL complaining about unimplemented keyword":

          (declare (ignore subskill))

k

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87ekpeh2dz.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Ps. Note to OP re "SBCL complaining about unimplemented keyword":
> 
>           (declare (ignore subskill))

Thanks.  The other fix is to implement the keyword ;-)

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87k6z6h2hq.fsf@david-steuber.com>
······@news.dtpq.com (Christopher C. Stacy) writes:

> It sounds like he's using delarative programming style to define an
> abstraction called a "skill".  That's not a purely syntactic issue.
> But perhaps he intends the SKILL macro to be used by people who are
> not Lisp programmers, and the minor syntax advantage the that macro
> provides will be easier for them to handle.

That is actually a much better way of explaining it than I would have
come up with.

The data in question could be in an XML file.  There are other more
complex collections of data that I haven't tried to tackle yet.  All
of that stuff could be represented using XML.

By using Lisp, I can have that level of flexibility (and more) in a
much more readable form (for humans).  The real kicker is it can be
compiled into machine code instead of interpreted data.  I'm sure
there must be some benefit to that.

Early on in Norvig's PAIP book there is a little demonstration of a
program to generate sentences from a set of rules that are in the form
of a Lisp list that an engine processes.  That is basicly the sort of
style I am trying to emulate except the problem is a bit more
complicated than see spot run.

The only pitfall in the your very nice explanation is that I may be
the only customer for this.  That is not the fault of your
explaination though.  If I could sell this, I would.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87pt8yh2yg.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> David Steuber wrote:
> 
>    Also, I want to have a seperate, identically
> > named macro that would take the skill definitions and produce XML
> > instead of Lisp.
> 
> Identically named? OK, so you have these (skill...) forms in a file
> and you change what they expand into by having a different macro
> definition for SKILL in place at...compile-time. ie, these skill files
> cannot just be FASLs? I think this is a mistake. You are moving
> runtime processing into compile time, such that you won't be able to
> have it both ways (skills loaded up in a hashtable and written to
> XML). ie, there you are testing happily away and you want to dump it
> to XML. Step 1, redefine SKILL. Nah.... <g>

The idea is to have a Lisp file that contains declarative expressions
for skills.  For the application proper, those lisp files would be
compiled into FASLs that are loaded into the image.

However, the second macro (if it gets written) would not be used for
the application.  It would be used to translate the skills into an XML
format that can be used by another program written in Java or
whatever.  The reuse would be for the skill declerations.  After all,
typing XML is a pita that no sane human would want to do.

> > But don't think that I am not constantly asking myself why the heck
> > I'm doing this rather than going the direct route.
> 
> Ah, yes, that old "there's gotta be a better way" harbinger of
> rewrites to come.

Not to mention the awkwardness of other as yet to be defined things
that can affect how skills work or be affected by skills.

I've got a book of the game rules that is written for humans.  It is a
fairly good specification for a computer program.  The only problem is
that humans can understand the rules (except for where there are some
unclear things) much more easily than finding a way to calculate
things by program.

> > As for subskills, here is an abbreviated example of how that is
> > intended to be used (unless I change my mind):
> > (skill craft "Craft" :subskills (foo "Foo" bar "Bar" baz "Baz") ...)
> > This would then give me:
> > (defparameter craft-foo (make-skill :name "Craft(Foo)" ...))
> 
> (Long) Hint: Surely you mean '(craft foo). ie, lose the string
> orientation (using them, concatenating them), use sexprs, and if you
> are stuffing skills in a hash table on the name, does the skill need
> to include its own name as part of the skill? Please note that I am
> note as it might appear critiquing your proposal so much as wondering
> if it could be Lispier.

At this stage I am still experimenting with implementation methods to
see what works best in Lisp.  What I posted was the sketch on a napkin
that leads to an outline for a rough draft ;-)

Certainly there are better ways to arrange the final format.  There
are probably also better ways to represent the input format as well.

> Another thing: this naming convention suggests to me that subskills
> are owned by their parents. I can see you want to dynamically add
> subskills by simply creating skills with the name (append skill-name
> (list sub-skill-name-extension)). Would it be more flexible to
> bifurcate the skill definition from the insersation-cum-subskill? Let
> the skill have an id (foo or bar or baz), and offer some other syntax
> for superskill specification. Then at load time skills could be pushed
> onto superskill subskill lists and instead of finding subskills by
> finding skills with the same root as myself, I just look to my list of
> subskills.

Subskills (as I call them) are really seperate skills that differ
mostly in name only.  However there are some rules that I don't know
how to represent in an automated way.

For example, the appraise skill lets you judge the monetary value of
something.  For example, you could appraise the value of a bow.  If
you have sufficient skill in '(craft bowmaking), then you are better
able to appraise the value of a bow.  However, '(craft blacksmithing)
would give you no such help.

> As you have noted elsewhere, 60s Lisp is still as modern as you
> wannabe. I think the symbols per se are OK, but you yourself are still
> going thru a Lispification so you are kinda using symbols in a half
> Lisp, half C kinda way, using them but also using strings and
> concatenating symbol-name strings into longer-symbols which should
> simply be lists of the symbols.

Yes, I still have some Lispification to go through.  My thinking is
very C like for a reason.  That is the language I have spent the most
time with (and C++).  Even with C++, I would be procedural in some
places and object oriented in other places of the same program.  Pure
approaches don't suit me well.  However, Lisp is a powerful tool and
the better I can think in its terms, the better I can take advantage
of that power.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <xNfrc.89551$Nn4.18767015@twister.nyc.rr.com>
David Steuber wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>David Steuber wrote:
>>
>>   Also, I want to have a seperate, identically
>>
>>>named macro that would take the skill definitions and produce XML
>>>instead of Lisp.
>>
>>Identically named? OK, so you have these (skill...) forms in a file
>>and you change what they expand into by having a different macro
>>definition for SKILL in place at...compile-time. ie, these skill files
>>cannot just be FASLs? I think this is a mistake. You are moving
>>runtime processing into compile time, such that you won't be able to
>>have it both ways (skills loaded up in a hashtable and written to
>>XML). ie, there you are testing happily away and you want to dump it
>>to XML. Step 1, redefine SKILL. Nah.... <g>
> 
> 
> The idea is to have a Lisp file that contains declarative expressions
> for skills.  For the application proper, those lisp files would be
> compiled into FASLs that are loaded into the image.

OK, but then two things:

(a) as someone suggested, why not just (with some stuff omitted)?:

        `(defparameter ,skill-name
            (make-skill ,@cleaned-up-skillargs))

(b) as for the defparameter thing, the problem I have is that the rest 
of the system now needs to be hard-coded to know about those special 
variables. If instead:

        `(setf (gethash *skillset* ,skill-name)
             (make-skill....))

the rest of the system just needs to know about *skillset*.

> 
> However, the second macro (if it gets written) would not be used for
> the application.  It would be used to translate the skills into an XML
> format that can be used by another program written in Java or
> whatever.  The reuse would be for the skill declerations.  After all,
> typing XML is a pita that no sane human would want to do.

I would just write a utility to convert the contents of *skillset* to 
XML format, after loading the compiled skill definition file(s). Or is 
there some advantage you see to having the skill source available to the 
(macro) function writing out the XML?

hth, kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87ad029uih.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> David Steuber wrote:
> > Kenny Tilton <·······@nyc.rr.com> writes:
> >
> >>David Steuber wrote:
> >>
> >>   Also, I want to have a seperate, identically
> >>
> >>>named macro that would take the skill definitions and produce XML
> >>>instead of Lisp.
> >>
> >>Identically named? OK, so you have these (skill...) forms in a file
> >>and you change what they expand into by having a different macro
> >>definition for SKILL in place at...compile-time. ie, these skill files
> >>cannot just be FASLs? I think this is a mistake. You are moving
> >>runtime processing into compile time, such that you won't be able to
> >>have it both ways (skills loaded up in a hashtable and written to
> >>XML). ie, there you are testing happily away and you want to dump it
> >>to XML. Step 1, redefine SKILL. Nah.... <g>
> > The idea is to have a Lisp file that contains declarative expressions
> > for skills.  For the application proper, those lisp files would be
> > compiled into FASLs that are loaded into the image.
> 
> OK, but then two things:
> 
> (a) as someone suggested, why not just (with some stuff omitted)?:
> 
>         `(defparameter ,skill-name
>             (make-skill ,@cleaned-up-skillargs))

I am not a Jedi yet.  I just read that post.  I like that macro much
better than mine.  I will be stealing it.

> (b) as for the defparameter thing, the problem I have is that the rest
> of the system now needs to be hard-coded to know about those special
> variables. If instead:
> 
>         `(setf (gethash *skillset* ,skill-name)
>              (make-skill....))
> 
> the rest of the system just needs to know about *skillset*.

Yes, I think this is the way to go.

> > However, the second macro (if it gets written) would not be used for
> > the application.  It would be used to translate the skills into an XML
> > format that can be used by another program written in Java or
> > whatever.  The reuse would be for the skill declerations.  After all,
> > typing XML is a pita that no sane human would want to do.
> 
> I would just write a utility to convert the contents of *skillset* to
> XML format, after loading the compiled skill definition file(s). Or is
> there some advantage you see to having the skill source available to
> the (macro) function writing out the XML?

I don't think how the XML gets generated is imortant.  I think a
utility function that walks the skillset hashtable would be perfectly
fine.  In fact, once I figure out all the rules I need I'm bound to
find all sorts of interdependencies that might make a utility the way
to go.  The utility would need to be able to follow the cross
references in order to mention them in the XML.  This would make the
utility act as a secondary sanity check if you will.

Either that, or it will be a feature I don't need and thus never gets
written.

Feedback here has been good.  I think I am definitely learning
something.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <rdOqc.661$g71.300@clgrps13>
Is this what you want?  It does run in LW


(defstruct skill
   name
   key-ability
   (trained-only nil)
   (armor-check-penalty nil)
   (check nil)
   (action nil)
   (try-again nil)
   (special nil)
   (synergy nil)
   (restriction nil)
   (untrained nil))

(defmacro skill (&rest rest &key symbol name key-ability
                  subskill trained-only armor-check-penalty
                  check action try-again special synergy
                  restriction untrained)
   "Create skills based on the skill structure"
   (declare (ignore symbol name key-ability subskill
                    trained-only armor-check-penalty
                    check action try-again special
                    synergy restriction untrained))
   (remf rest :symbol)
   (remf rest :subskill)
   `(defparameter ,symbol ,(apply #'make-skill rest)))

CL-USER 10 > (macroexpand-1 '(skill :symbol apraise :name "Apraise" :key-ability :int 
:try-again t :synergy craft :special appraise-special-fn))
(DEFPARAMETER APRAISE #S(SKILL NAME "Apraise" KEY-ABILITY :INT TRAINED-ONLY NIL 
ARMOR-CHECK-PENALTY NIL CHECK NIL ACTION NIL TRY-AGAIN T SPECIAL APPRAISE-SPECIAL-FN 
SYNERGY CRAFT RESTRICTION NIL UNTRAINED NIL))
T

CL-USER 11 > (skill :symbol apraise :name "Apraise" :key-ability :int :try-again t 
:synergy craft :special appraise-special-fn)
APRAISE

CL-USER 12 > apraise
#S(SKILL NAME "Apraise" KEY-ABILITY :INT TRAINED-ONLY NIL ARMOR-CHECK-PENALTY NIL CHECK 
NIL ACTION NIL TRY-AGAIN T SPECIAL APPRAISE-SPECIAL-FN SYNERGY CRAFT RESTRICTION NIL 
UNTRAINED NIL)

CL-USER 13 >

Wade
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <waOqc.49062$mX.18153539@twister.nyc.rr.com>
Wade Humeniuk wrote:

> Is this what you want?  It does run in LW
> 
> 
> (defstruct skill
>   name
>   key-ability
>   (trained-only nil)
>   (armor-check-penalty nil)
>   (check nil)
>   (action nil)
>   (try-again nil)
>   (special nil)
>   (synergy nil)
>   (restriction nil)
>   (untrained nil))
> 
> (defmacro skill (&rest rest &key symbol name key-ability
>                  subskill trained-only armor-check-penalty
>                  check action try-again special synergy
>                  restriction untrained)
>   "Create skills based on the skill structure"
>   (declare (ignore symbol name key-ability subskill
>                    trained-only armor-check-penalty
>                    check action try-again special
>                    synergy restriction untrained))
>   (remf rest :symbol)
>   (remf rest :subskill)
>   `(defparameter ,symbol ,(apply #'make-skill rest)))

Since remf is destructive, is it necessary to copy-list rest?

kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <KBOqc.742$g71.377@clgrps13>
Kenny Tilton wrote:


>>
>> (defmacro skill (&rest rest &key symbol name key-ability
>>                  subskill trained-only armor-check-penalty
>>                  check action try-again special synergy
>>                  restriction untrained)
>>   "Create skills based on the skill structure"
>>   (declare (ignore symbol name key-ability subskill
>>                    trained-only armor-check-penalty
>>                    check action try-again special
>>                    synergy restriction untrained))
>>   (remf rest :symbol)
>>   (remf rest :subskill)
>>   `(defparameter ,symbol ,(apply #'make-skill rest)))
> 
> 
> Since remf is destructive, is it necessary to copy-list rest?

Well make-skill barfs on :symbol and :subskill keyword arguments.
So I destructively removed it from the rest list.  Since I
do not need the original rest I should be able to destructively
modify it.

Wade
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <PjRqc.49067$mX.18207366@twister.nyc.rr.com>
Wade Humeniuk wrote:
> Kenny Tilton wrote:
> 
> 
>>>
>>> (defmacro skill (&rest rest &key symbol name key-ability
>>>                  subskill trained-only armor-check-penalty
>>>                  check action try-again special synergy
>>>                  restriction untrained)
>>>   "Create skills based on the skill structure"
>>>   (declare (ignore symbol name key-ability subskill
>>>                    trained-only armor-check-penalty
>>>                    check action try-again special
>>>                    synergy restriction untrained))
>>>   (remf rest :symbol)
>>>   (remf rest :subskill)
>>>   `(defparameter ,symbol ,(apply #'make-skill rest)))
>>
>>
>>
>> Since remf is destructive, is it necessary to copy-list rest?
> 
> 
> Well make-skill barfs on :symbol and :subskill keyword arguments.

Understood.

> So I destructively removed it from the rest list.  Since I
> do not need the original rest I should be able to destructively
> modify it.

Well this bit gives me pause:

"3.4.1.3 A specifier for a rest parameter

.....The value of a rest parameter is permitted, but not required, to 
share structure with the last argument to apply."

macros cannot be apply'ed, but this kind of thing always has me vervous 
about destructively modify arguments (unless of course that is the 
function's job).

kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <4yTqc.566$gx1.64@clgrps12>
Kenny Tilton wrote:

> macros cannot be apply'ed, but this kind of thing always has me vervous 
> about destructively modify arguments (unless of course that is the 
> function's job).

I also have lots of verve when I encounter these things. :)

Wade
From: ·········@random-state.net
Subject: Re: macro-biology
Date: 
Message-ID: <c8gnsa$ani3e$1@midnight.cs.hut.fi>
Wade Humeniuk <····································@telus.net> wrote:

>> Since remf is destructive, is it necessary to copy-list rest?

> Well make-skill barfs on :symbol and :subskill keyword arguments.
> So I destructively removed it from the rest list.  Since I
> do not need the original rest I should be able to destructively

Destructively modifying &rest list is no such a good idea: the system
is not required to cons a fresh one -- you could eg. end up modifying a
list that was passed to an APPLY earlier.

Cheers,

  -- Nikodemus
From: Kalle Olavi Niemitalo
Subject: Re: macro-biology
Date: 
Message-ID: <87hducnkao.fsf@Astalo.kon.iki.fi>
Wade Humeniuk <····································@telus.net> writes:

> Well make-skill barfs on :symbol and :subskill keyword arguments.
> So I destructively removed it from the rest list.  Since I
> do not need the original rest I should be able to destructively
> modify it.

From section 3.1.2.1.2.2: "The consequences are undefined if a macro
function destructively modifies any part of its form argument."
From section 3.4.4.1.2, it seems that the rest parameter will be
bound to the appropriate tail of the original form, not to a copy.
(The explicitly vague wording in 3.4.1.3 does not apply here,
because the macro function gets the entire form as just one
argument, rather than spread with APPLY.)

In CMUCL release-18e-branch, SBCL 0.8.9.46, and CLISP 2.32:

  (defmacro clobber (&rest args)
    (incf (first args)))        ; undefined consequences

  (list #1=(clobber 0) #1# #1#)
  ;; => (1 2 3)
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87vfiqh45z.fsf@david-steuber.com>
Wade Humeniuk <····································@telus.net> writes:

> Is this what you want?  It does run in LW
> 
> (defmacro skill (&rest rest &key symbol name key-ability
>                   subskill trained-only armor-check-penalty
>                   check action try-again special synergy
>                   restriction untrained)
>    "Create skills based on the skill structure"
>    (declare (ignore symbol name key-ability subskill
>                     trained-only armor-check-penalty
>                     check action try-again special
>                     synergy restriction untrained))
>    (remf rest :symbol)
>    (remf rest :subskill)
>    `(defparameter ,symbol ,(apply #'make-skill rest)))

It's an improvement over what I've got.  I see from the replies that
remf could be a problem, but that can be delt with.  I saw the other
replies, so I'll take that all into consideration.  It needs to work
with SBCL.  Beyond that, portability is not a huge concern.  But this
is a case where ANSI compliance doesn't need to be gratuitously
violated.

Also the subskill example that you probably missed isn't handled in
this case, but it sure makes it look a lot easier to wedge in.

Thanks.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <nngrc.2904$J02.152@edtnps84>
David Steuber wrote:

> 
> Also the subskill example that you probably missed isn't handled in
> this case, but it sure makes it look a lot easier to wedge in.

Piecing together your other comments about subskill, here is some
more code

(defstruct skill
   name
   key-ability
   (trained-only nil)
   (armor-check-penalty nil)
   (check nil)
   (action nil)
   (try-again nil)
   (special nil)
   (synergy nil)
   (restriction nil)
   (untrained nil))

(defmacro skill (&rest rest &key symbol name key-ability
                  subskill trained-only armor-check-penalty
                  check action try-again special synergy
                  restriction untrained)
   "Create skills based on the skill structure"
   (declare (ignore key-ability trained-only armor-check-penalty
                    check action try-again special
                    synergy restriction untrained))
   (let* ((struct-args (let ((list (copy-list rest)))
                         (remf list :symbol)
                         (remf list :subskill)
                         (remf list :name)
                         list))
          (subskill-defparameters
           (loop for (subsym string) on subskill by #'cddr
                 collect `(defparameter ,(intern (format nil "~A-~A" symbol subsym))
                            (make-skill :name ,(format nil "~A(~A)" (string-capitalize name)
                                                       (string-capitalize string))
                                        ,@struct-args)))))

     `(progn
        ,@subskill-defparameters
        (defparameter ,symbol (make-skill :name ,name ,@struct-args)))))

CL-USER 3 > (pprint (macroexpand-1 '(skill :symbol craft :name "Craft" :key-ability :int
                                            :try-again t
                                            :subskill (foo "foo" bar "bar"))))

(PROGN
   (DEFPARAMETER CRAFT-FOO (MAKE-SKILL :NAME "Craft(Foo)" :KEY-ABILITY :INT
                            :TRY-AGAIN T))
   (DEFPARAMETER CRAFT-BAR (MAKE-SKILL :NAME "Craft(Bar)" :KEY-ABILITY :INT
                            :TRY-AGAIN T))
   (DEFPARAMETER CRAFT (MAKE-SKILL :NAME "Craft" :KEY-ABILITY :INT
                        :TRY-AGAIN T)))

CL-USER 4 >

As to whether or not this what you should (or want) to really do this is up to
you.  The code above is hardly tested, but I hope it is helpful.

Wade
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <874qqa9u8m.fsf@david-steuber.com>
Wade Humeniuk <········@telus.delete.net> writes:

> As to whether or not this what you should (or want) to really do this is up to
> you.  The code above is hardly tested, but I hope it is helpful.

Wow!

I wish I could turn out code that fast.  I'm still exploring, but the
code you posted is most certainly helpful to me.  Even if I do not go
the exact route, at least I have an example of being able to produce
multiple top level forms from a single macro call.

Thanks.

You won't believe the time I spent getting to what I came up with.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <Uoqrc.2240$gx1.1400@clgrps12>
David Steuber wrote:


> You won't believe the time I spent getting to what I came up with.
> 

Don't be dissuaded that things are taking a long time.  Its good that
you are tackling a more difficult problem while learning Lisp.  Doing
simple problems to learn Lisp is OK, but one does not get to see
Lisp in action unless one codes against some harder problems.

Wade
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87zn81hzrf.fsf@david-steuber.com>
Wade Humeniuk <········@telus.delete.net> writes:

> David Steuber wrote:
> 
> > You won't believe the time I spent getting to what I came up with.
> 
> Don't be dissuaded that things are taking a long time.  Its good that
> you are tackling a more difficult problem while learning Lisp.  Doing
> simple problems to learn Lisp is OK, but one does not get to see
> Lisp in action unless one codes against some harder problems.

I'm trying not to be dissuaded.  It took me a long time to learn C
too.  At least Lisp doesn't slam me with long code, compile, test
cycles.

I also think I may be beginning to "get it".  Perhaps I can sound off
here to see if I am.  I kind of like the thread subject line ;-)

I think what I am beginning to get is the Lisp as a Programmable
Programming Language aspect.  A macro can be formulated to generate
essentially any syntacticly legal Lisp code at compile time.  Those
tools that other languages (like Java, C++, Objective-C, etc) have
available to them to generate huge masses of boiler-plate code can be
implemented in Lisp as macros.  That isn't the knock my socks off
part.  Everyone has seen code generators.  Everyone has seen cpp style
macro expansion.  What knocks my socks off is the fact that *the full
power of Lisp is available at /compile-time/ for code generation*.
Any Lisp expression that can be used in a top level form can go inside
a macro definition.  I don't mean inside the backquote either.  Nor
are you limited in the number of backquoted expressions.

As a slightly concrete example, let's say you are writing windowing
apps that always uses the same boiler-plate code.  You can have some
forms that look like this:

(defmacro make-boiler-plate (main-fn &rest options-plist) ...)

(defun my-main-fn (...) ...)

...

(make-boiler-plate #'my-main-fn :foo-option :baz ...)

The function my-main-fn would have a lambda-list that is expected by
make-boiler-plate.  The macro make-boiler-plate would do just what it
says.  It would produce at compile time all that boiler-plate code
that you normally use a wizard for if you are a Java programmer.  The
options that make-boiler-plate takes would be control the type of
boiler-plate produced just as you do with the dialogs in the wizard.
Finally, you supply it with your function that actually specializes
the application.

The macro's options can be expanded upon as different shape cookies
become supported.  Since the macro is Lisp, not some external
generator, you can change your mind about the options you pass in pain
free.  There are no bazaar comments inserted by the code generator to
clutter your code base just so that the code generator stands a chance
of being used again during application development.

RAD capability is built into the language.

I am currently just held back by trying to find the words to say what
I want to say and not really knowing exactly what I want to say.  Java
gives me the exact same pain and adds to it in that it wants me to
specify in advance exactly what I want to say.

One caveat.  I'm not saying that just because C++, Java, and other
languages benefit from external tools to generate boiler-plate code
that Lisp would also derive the same benefit from boiler-plate code
generation.  I'm just saying that you can do it with the built in
language facilities.  The library code that make-boiler-plate assumes
you are using just might be easy enough to use more directly.  Also,
make-boiler-plate would belong to that library, not your specific
application code.  Still, if ever there is a pattern that creeps into
an application, there is an opportunity to factor that into a simpler
expression.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <L9mrc.89555$Nn4.18848930@twister.nyc.rr.com>
Wade Humeniuk wrote:

> David Steuber wrote:
> 
>>
>> Also the subskill example that you probably missed isn't handled in
>> this case, but it sure makes it look a lot easier to wedge in.
> 
> 
> Piecing together your other comments about subskill, here is some
> more code

Nice. Starting from that but then throwing out the client's 
specification, we can simplify further. It occurred to me that by the 
spec the only indication post macro-expansion of the super-subskill 
relationship was the hypenated structure of the defparameter. Not good. 
It also occurred to me that the macro does not really need to make all 
the keys explicit now that we are using your trick of just remf-ing the 
ones that don't belong and passing them along to make-skill. So:

(defvar *skillset*)

(defstruct skill
   full-name
   super-skill
   key-ability
   (trained-only nil)
   (armor-check-penalty nil)
   (check nil)
   (action nil)
   (try-again nil)
   (special nil)
   (synergy nil)
   (restriction nil)
   (untrained nil))

(defmacro def-skill-atom (name &rest args &key super-skill 
&allow-other-keys)
   (let ((full-name (append super-skill (list name))))
   `(setf (gethash ',full-name *skillset*)
      (make-skill :full-name ',full-name
        ,@(let ((args (copy-list args)))
            (remf args :super-skill)
            args)))))

#+test
(macroexpand-1 '(def-skill-atom hack :super-skill (software develop)
                   :check t :action 'debug))

#+becomes
(setf (gethash '(software develop hack) *skillset*)
       (make-skill :full-name '(software develop hack) :check t :action 
'debug))

(defmacro def-skill (name &rest args &key super-skill sub-skills 
&allow-other-keys)
   (let* ((skill-args (let ((args (copy-list args)))
                        (remf args :sub-skills)
                        args)))
     `(progn
        (def-skill-atom ,name ,@skill-args)
        ,@(loop for (sub-name . sub-args) in sub-skills
                collecting `(def-skill-atom ,sub-name
                                :super-skill ,(append super-skill (list 
name))
                              ,@sub-args)))))

#+test
(macroexpand-1 '(def-skill develop :super-skill (software)
                   :check t :action 'roll-out
                   :sub-skills ((hack :check 9 :action 'slash)
                                (debug :check 42 :action 'guess))))

#+becomes
(progn (def-skill-atom develop :super-skill (software) :check t :action
                        'roll-out)
        (def-skill-atom hack :super-skill (software develop) :check 9 
:action
                        'slash)
        (def-skill-atom debug :super-skill (software develop) :check 42 
:action
                        'guess))

#+final
(progn
   (setf *skillset* (make-hash-table :test 'equal))
   (def-skill develop :super-skill (software)
                   :check t :action 'roll-out
                   :sub-skills ((hack :check 9 :action 'slash)
                                (debug :check 42 :action 'guess)))
   (maphash (lambda (key value)
              (print `(key is ,key))
              (describe value))
      *skillset*))

If we do not want to have to quote things in the skill language (eg, 
code ":action slash" instead of ":action 'slash", then there is more 
work to do.

kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Kenny Tilton
Subject: Re: macro-biology
Date: 
Message-ID: <xlnrc.89557$Nn4.18873863@twister.nyc.rr.com>
Kenny Tilton wrote:

> If we do not want to have to quote things in the skill language (eg, 
> code ":action slash" instead of ":action 'slash", then there is more 
> work to do.

But not much, and then we also get to lose that copy-list/remf ugliness:

(defmacro def-skill-atom (name &rest args &key super-skill 
&allow-other-keys)
   (let ((full-name (append super-skill (list name))))
   `(setf (gethash ',full-name *skillset*)
      (make-skill :full-name ',full-name
        ,@(loop for (kw kwv) on args by #'cddr
                unless (eq kw :super-skill)
                nconcing `(,kw ',kwv))))))

Other adjustments to prior code now required, btw.

kenny

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Wade Humeniuk
Subject: Re: macro-biology
Date: 
Message-ID: <Gjqrc.2233$gx1.1597@clgrps12>
Kenny Tilton wrote:

> 
> Nice. Starting from that but then throwing out the client's 
> specification, we can simplify further. It occurred to me that by the 
> spec the only indication post macro-expansion of the super-subskill 
> relationship was the hypenated structure of the defparameter. Not good. 
> It also occurred to me that the macro does not really need to make all 
> the keys explicit now that we are using your trick of just remf-ing the 
> ones that don't belong and passing them along to make-skill. So:

Well Dave's intention seem to be create a simulation in some RPG.
Skills seem to have some global attributes but would also have
person specific skill levels.  Events in the simulated world would
be calculated based on the locale,  the persons (represented by
their skills and other attributes) and other factors.  I suspect
Dave would be happier with a CLOS solution, where skills are
subclassed and then instances created for each person.  You have
alluded to this by using superskills.  Whether this approach is
sufficient is up for grabs.

Wade
From: David Steuber
Subject: Re: macro-biology
Date: 
Message-ID: <87u0y9hz91.fsf@david-steuber.com>
Wade Humeniuk <········@telus.delete.net> writes:

> Kenny Tilton wrote:
> 
> > Nice. Starting from that but then throwing out the client's
> > specification, we can simplify further. It occurred to me that by
> > the spec the only indication post macro-expansion of the
> > super-subskill relationship was the hypenated structure of the
> > defparameter. Not good. It also occurred to me that the macro does
> > not really need to make all the keys explicit now that we are using
> > your trick of just remf-ing the ones that don't belong and passing
> > them along to make-skill. So:
> 
> Well Dave's intention seem to be create a simulation in some RPG.
> Skills seem to have some global attributes but would also have
> person specific skill levels.  Events in the simulated world would
> be calculated based on the locale,  the persons (represented by
> their skills and other attributes) and other factors.  I suspect
> Dave would be happier with a CLOS solution, where skills are
> subclassed and then instances created for each person.  You have
> alluded to this by using superskills.  Whether this approach is
> sufficient is up for grabs.

I probably will converge on a CLOS solution.

It's very tempting to try and program the thing all at once.  That is
of couse and impossible task.  I need to rein myself in a bit and
build it a piece at a time.  My most immediate need is a facility for
simply keeping track of character statistics.  There is an existing
Java program that does that, but I have found it unusable.

It would be way cool to come up with something that blows away
Neverwinter Nights, but I don't think I can do that in any language.

-- 
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
From: Svein Ove Aas
Subject: Re: macro-biology
Date: 
Message-ID: <_vLpc.1912$eH3.43798@news4.e.nsc.no>
Marco Baringer wrote:

> David Steuber <·····@david-steuber.com> writes:
> 
>> First question.  Can a macro only expand into code?  Or can I define a
>> macro that will expand into XML for printing?  This expansion may be
>> into a string that I pass to format.  The mechanism isn't as important
>> as the ability to do so.  Here are a couple examples in pseudolisp
>> with the output after printing as with princ or format:
> 
> a macro can only expand into code, that code will be eval'd. end of
> the story (caveat: this assumes you asked lisp to eval the macro form,
> if you're just passing a list to macroexpand things are different).

I don't see why.
It seems to me that the following code is perfectly valid:

(defmacro test () "This ain't code")

(defun print-test (nr)
  (loop repeat nr
   with text = (test)
   do (print text)))


Macros can presumably return *any* valid Lisp form, and in fact it isn't
possible to write a macro that doesn't.

Sure, you can put the macro call where the returned data will get
compiled/eval'd, but you can equally well assign it to a variable.
From: Barry Margolin
Subject: Re: macro-biology
Date: 
Message-ID: <barmar-F9F607.11571916052004@comcast.dca.giganews.com>
In article <····················@news4.e.nsc.no>,
 Svein Ove Aas <··············@brage.info> wrote:

> Marco Baringer wrote:
> 
> > David Steuber <·····@david-steuber.com> writes:
> > 
> >> First question.  Can a macro only expand into code?  Or can I define a
> >> macro that will expand into XML for printing?  This expansion may be
> >> into a string that I pass to format.  The mechanism isn't as important
> >> as the ability to do so.  Here are a couple examples in pseudolisp
> >> with the output after printing as with princ or format:
> > 
> > a macro can only expand into code, that code will be eval'd. end of
> > the story (caveat: this assumes you asked lisp to eval the macro form,
> > if you're just passing a list to macroexpand things are different).
> 
> I don't see why.
> It seems to me that the following code is perfectly valid:
> 
> (defmacro test () "This ain't code")

That's expanding into code, since strings are self-evaluating in Common 
Lisp.

Try changing that to:

(defmacro test () '(this-aint . code))

and see how well print-test works (don't forget to recompile print-test 
after redefining the macro).

> 
> (defun print-test (nr)
>   (loop repeat nr
>    with text = (test)
>    do (print text)))

> Sure, you can put the macro call where the returned data will get
> compiled/eval'd, but you can equally well assign it to a variable.

The source of an assignment *is* compiled/evaled.

The only way to make use of a macro that doesn't expand into valid code 
is if you never use it in an expression context, only by expanding it 
manually with MACROEXPAND.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***