[racket] Something to achieve "define-syntax-parameter-for-syntax" or "set!-for-syntax"?

From: Sean Kanaley (skanaley at gmail.com)
Date: Sun Jan 5 09:02:55 EST 2014

Hello,

First the short question: is there a way that user code can set some sort
of in-effect global variable to determine how a library macro will expand?
The problem I have is there doesn't seem to be a way to combine the
concepts of parameters/globals and transformer environments.

Long part in case it's not clear why I'm trying to do this or if someone
knows a better way (I was hoping writing this would cause me to figure it
out and avoid having to ask the question, as is usually the case.  It did
not work.):

I am attempting to define a library macro.  This macro's expansion should
be based on the user's global parameterization of it.  It is a macro to
create an association list between "commands" and functions for keyboard
input (or any input).  The association list looks like this for example:

'([left (lambda (params ...) (code-to-move-left))]
  [right (lambda (params ...) (code-to-move-right))])

where there is some config file like:

a = left
d = right

that associates keys to commands, and ultimately the library associates
keys to code by combining the two associations transitively.

The macro named "commands" to build the first table is written to save on
the duplicate "(lambda (param ...)" portion, so the user code building the
alist goes like this:

(commands (params ...)
  (left (code-to-move-left))
  (right (code-to-move-right)))

The problem comes in when the user does not define commands all at once.
Two calls to the "commands" macro require using the same parameter list,
since there is a top-level "run-input" function that checks if a key is
down and runs the associated function, passing in the generic parameter set
(regardless of which / if any keys that are down).  So I want to have
"commands" be defined something like this:

(define-syntax (commands stx)
  (syntax-case stx ()
    [(_ (c f) ...)
     #`(list (cons (symbol->string 'c)
                   (λ #,input-params f))
             ...)]))

Where input-params is bound to the syntax of the parameter list.  The usage
is ideally:

(define users-constant #'(state delta-time))

(syntax-paramterize or set! or whatever on input-params to users-constant
  (commands
    (left (move-left! state (* speed delta-time)))
    (right (move-right! etc...

expanding into:

'([left (lambda (state delta-time) (move-left! state (* speed delta-time)))]
  [right etc...])

But I can't figure it out.

By placing this hypothetical extension of the library code into the user
code, I can write this as a wrapper macro on "commands" that shares the
user's constant piece of syntax using datum->syntax:

(define-for-syntax (input-params stx)
  (datum->syntax stx '(state delta-time)))

(define-syntax (cmds stx)
  (syntax-case stx ()
    [(_ body ...)
     #`(commands #,(input-params stx)
           body ...)]))

and now all calls to cmds will share a single parameter list as required.
But this is weak because this code will be the same for every user except
the actual parameter list embedded within input-params definition, so I'm
looking for a way to get the above functionality into the library, yet
still have the user define the "'(state delta-time)" portion themselves.
Basically copy paste the "cmds" definition into the library, and then I
would just need "set!-for-syntax input-params '(state delta-time)" to be
possible.

One day I hope to have a Racket + OpenGL answer to something like XNA.
That day is not today.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140105/d47247b5/attachment.html>

Posted on the users mailing list.