I think you're looking for `keyword-apply`. It's true that `eval` works as way to get reflective operations in general, but it's better (again, for error checking and for efficiency) when a language construct is accompanied with specific reflective operations. In the case of keyword arguments, those operations include `make-keyword-procedure`, `keyword-apply`, and `procedure-reduce-keyword-arity`.
It's not always obvious which operations to include, and `procedure-reduce-keyword-arity`, for one, wasn't included originally. I think I might also have trouble defining "reflective operation" precisely, as opposed to having constructs that support abstraction more directly (such as allowing the superclass position of a `class` form to be an expression). But if `keyword-apply` didn't exist, then this example would make me think that some form of abstraction was missing for keyword arguments, instead of seeming like a good use of `eval`. At Sat, 9 Aug 2014 10:10:08 -0400, Sean Kanaley wrote: > There's a simple enough example I think: apply with keyword parameters. > Apply has that built-in..sort of...but the list is supposed to be provided > inline to APPLY, seemingly requiring apply to be applied (e.g. (apply apply > (cons *thefunctiontoapply* params))), except keywords can't be expressions > anyway. I have a bunch of card definitions for Dominion with many defaults: > > (struct card (... actions buys ...)) > > (define (make-card ... #:actions actions #:buy buys ...) > ...) > > The non-keyword-requiring way is > > (define CARDS > (map (\ (lst) (apply make-card lst)) > '([... 1 1 ...] > [... 2 0 ...]))) > > The keyword way is > > ;ns is namespace > (mapply (\ (lst) (eval `(apply make-card ',(car l) ,@(cdr l)) ns)) > '([(...) #:actions 1 #:buys 1 ...])) > > Short of making a big macro to take some exact format and get it to work > with keywords and all that, eval seems to be just what is needed. > > > On Sat, Aug 9, 2014 at 8:27 AM, Neil Van Dyke <n...@neilvandyke.org> wrote: > > > Sounds like a good rule of thumb. Two suggestions to add: > > > > * Maybe there could also be a second rule of thumb, like, "If you need > > arbitrary Racket expressions, then consider whether you can do it with one > > of the following patterns: [list some patterns involving combinations of > > syntax extension, custom #lang, dynamic requires, considering whether > > config files can actually be compile-time #lang, etc.]" This is less > > important than the first rule of thumb. > > > > * When we list typical newbie cases that don't actually require "eval", we > > can expect that newbie will immediately want an example of the non-"eval" > > way to do that typical thing. At the very least, an example showing, say, > > good use of hashes in parameters, with a sensible thin abstraction layer > > over it, for that case. These examples would be tedious to work through > > and write up well, but someday some knowledgeable and benevolent person > > will do it. (I am not this person. Book royalties aren't enough to ease > > the pain. I'd rather that newbies just never heard of "eval" or were scared > > away from it, rather than having to talk them down off the ledge all the > > time.) > > > > Neil V. > > > > > > Eli Barzilay wrote at 08/09/2014 07:31 AM: > > > > I think that I ran into a nice way to discourage eval except when > >> needed: the rule of thumb is to only use eval when you need to evaluate > >> any arbitrary (Racket) expression. It sounds simplistic but it covers > >> lots of cases that make newbies run to eval: > >> > >> * I just want to get the value of a variable whose name is held in x > >> > >> * More common: I have a symbol/string that names a function, I just need > >> to call that function > >> > >> * I need to keep an update-able mapping from names to values, just like > >> what the toplevel does > >> > >> * I want to let people write an arithmetic expression instead of a > >> number > >> > >> In such cases questions like "do you need allow calling all functions", > >> and "do you need to handle lambda expressions" have negative answers. > >> > >> > >> > >> On Sun, Jul 27, 2014 at 4:16 PM, Neil Van Dyke <n...@neilvandyke.org> > >> wrote: > >> > >>> Maybe there should be a periodic public service announcement about not > >>> using > >>> "eval". This time I will communicate in FAQ format: > >>> > >>> Q: How do I use eval? > >>> A: Don't use eval. > >>> > >>> Q: But don't so many academic books feature eval prominently, so doesn't > >>> that mean I should use try to eval? > >>> A: Those books use eval for pedagogic reasons, or because the author is > >>> enamored of some theoretical appeal of eval, or because the author wants > >>> to > >>> watch the world burn. Don't use eval. > >>> > >>> Q: But, but, but, I am just starting to learn, and eval seems to do what > >>> I > >>> need. > >>> A: Eval is almost certainly not what you want. Learn how to use the > >>> other > >>> basics effectively. Don't use eval. > >>> > >>> Q: I now am very comfortable with the language, I am aware that I should > >>> avoid eval in almost all cases, and I can tell you why eval is actually > >>> the > >>> right thing in this highly unusual case. > >>> A: Cool, that's why eval is there. > >>> > >>> Neil V. > >>> > >>> > >>> > > ____________________ > > Racket Users list: > > http://lists.racket-lang.org/users > > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users