From: ···············@gmail.com
Subject: Abstracting functions in DSLs
Date: 
Message-ID: <1154469014.194432.49250@m73g2000cwd.googlegroups.com>
Greetings,

I've created a simple embedded language for defining "missions" in the
game I work on (vendetta-online.com).  It's been a really wonderful
experience being able to abstract almost anything I might copy, paste,
and modify in another language.

But... there are an increasing number of cases where I've been defining
a function with labels inside a mission definition so that the function
closes over the environment of the mission (which is *quite* complex).
In a few general-enough cases, I've added the function definitions to
the macro expansion of all missions, but those are the exceptions.  The
functions I define within the mission-definition, and their use within
eachother and the rest of the mission-code, are *much* more readable
when I don't have to pass in all the variables it does (or might) use,
but they are beginning to make my mission-definitions long enough that
I find myself using search just to find my place within the same
definition.  I could obviously define them as macros outside the
defmission, relying on variable-capture to get all the per-mission
values it might want, but that just *feels* wrong.  I don't know if
there really is a solution, but I'd appreciate any advice.

~Michael Warnock

From: ·············@specastro.com
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <1154472099.769241.12110@m79g2000cwm.googlegroups.com>
···············@gmail.com wrote:

> I could obviously define them as macros outside the
> defmission, relying on variable-capture to get all the per-mission
> values it might want

Would macrolet help your situation?

Glenn
From: Ken Tilton
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <KFQzg.15$H17.3@fe11.lga>
···············@gmail.com wrote:
> Greetings,
> 
> I've created a simple embedded language for defining "missions" in the
> game I work on (vendetta-online.com).  It's been a really wonderful
> experience being able to abstract almost anything I might copy, paste,
> and modify in another language.
> 
> But... there are an increasing number of cases where I've been defining
> a function with labels inside a mission definition so that the function
> closes over the environment of the mission (which is *quite* complex).
> In a few general-enough cases, I've added the function definitions to
> the macro expansion of all missions, but those are the exceptions.  The
> functions I define within the mission-definition, and their use within
> eachother and the rest of the mission-code, are *much* more readable
> when I don't have to pass in all the variables it does (or might) use,
> but they are beginning to make my mission-definitions long enough that
> I find myself using search just to find my place within the same
> definition.  I could obviously define them as macros outside the
> defmission, relying on variable-capture to get all the per-mission
> values it might want, but that just *feels* wrong.  I don't know if
> there really is a solution, but I'd appreciate any advice.

 From memory (but I think I have it right):

"But Jesus said, Suffer captured variables, and forbid them not, to come 
unto thine macro bodies: for of such is are DSLs made."

Matthew 19:something. Anyway, yeah, come on, it is a DSL, these 
variables are like internals. Do you worry that some Lisp binding 
further down in the code works because its compiled incarnation is using 
a register setup by the compilation of some other HLL code? That is how 
I look at it: my outer DSL macros set up some state, my inner ones tap 
into it. Clockwork. (I should mention at this juncture that, yes, I do 
this all the time and I have come to see the Deep Goodness of capture, 
ie featureness vs bugness.)

The other message from god can be recognized in what seems to be the 
case from what you said: it would be a no-brainer to do this. The 
variables your inner macros are trying to capture will /always/ be 
there. Why is that? Because there is some regularity to what you are 
building that says the inner guys really are inner to the other code 
setting up the variables to be captured, meaning it is safe and sound to 
code this way. If, however, you are playing the same game and suddenly a 
quite natural use of a macro fails to compile because the captured 
variables are not in the lexical scope, then you have taken a wrong turn 
-- possibly not in the macro, possibly in the structuring of the other 
code in which using such a macro seemed natural (or possibly you 
reexamine the usage and realize it itself was no so appropriate after all.)

Can I get an Amen?

hth, kt


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

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Matthew D Swank
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <pan.2006.08.02.02.39.45.738874@c.net>
On Tue, 01 Aug 2006 14:50:14 -0700, ···············@gmail.com wrote:

> I could obviously define them as macros outside the
> defmission, relying on variable-capture to get all the per-mission
> values it might want, but that just *feels* wrong.

Echoing Kenny's answer, this is a (common ?) way to define the context of
an operation in a way that can still be closed over*-- much like the 
binding "this" or "self" in a messaging passing language.  Obviously if
you still want to pass all the state functionally in a compact way, you
could could bundle it in a single object.


Matt

*unlike special variables
-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Matthew D Swank
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <pan.2006.08.02.03.04.27.236219@c.net>
On Tue, 01 Aug 2006 21:39:46 -0500, Matthew D Swank wrote:

> this is a (common ?) way to define the context of
> an operation in a way that can still be closed over

In fact, the first example that popped into my head is from CLOS:

CL-USER> (defmethod foo (o)
           'bar)
STYLE-WARNING: implicitly creating new generic function FOO
#<STANDARD-METHOD FOO (T) {B0D9341}>
CL-USER> (defmethod foo ((o list))
           (values 'baz #'call-next-method))
#<STANDARD-METHOD FOO (LIST) {B21E8A1}>
CL-USER> (multiple-value-bind (1st next) (foo nil)
           (list 1st (funcall next)))
(BAZ BAR)
CL-USER> 

This makes call-next-method look a continuation.  I wonder if anyone has
implemented CPS just by using Common Lisp's generic function protocol.


Matt
-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Andreas Hinze
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <44D09B47.9030905@snafu.de>
Hi

···············@gmail.com wrote:
> Greetings,
> 
> I've created a simple embedded language for defining "missions" in the
> game I work on (vendetta-online.com).  

Out of curiosity: What language do you use for implementation
the engine ?

Regards
AHz
From: ········@gmail.com
Subject: Re: Abstracting functions in DSLs
Date: 
Message-ID: <1154566319.028541.250840@i3g2000cwc.googlegroups.com>
> But... there are an increasing number of cases where I've been defining
> a function with labels inside a mission definition so that the function
> closes over the environment of the mission (which is *quite* complex).
> In a few general-enough cases, I've added the function definitions to
> the macro expansion of all missions, but those are the exceptions.  The
> functions I define within the mission-definition, and their use within
> eachother and the rest of the mission-code, are *much* more readable
> when I don't have to pass in all the variables it does (or might) use,
> but they are beginning to make my mission-definitions long enough that
> I find myself using search just to find my place within the same
> definition.  I could obviously define them as macros outside the
> defmission, relying on variable-capture to get all the per-mission
> values it might want, but that just *feels* wrong.  I don't know if
> there really is a solution, but I'd appreciate any advice.

PROGV?

    http://www.lispworks.com/documentation/HyperSpec/Body/s_progv.htm