rit@killdeer.stanford.edu (Jean-Francois Rit) (03/17/90)
What is an elegant solution to implement the following function: (defxxx with-bindings (b-list s-exprs) "evaluates the s-exprs in an implicit progn. If the argument s-exprs contains free variables, they are bound according to b-list. Example: (setq sub '((?x (1 2)) (?y (3 5))) clause '(+ (car ?x) (cadr ?y))) --> (+ (car ?x) (cadr ?y)) (with-bindings sub clause) --> 6") Note that a macro expanding to a let won't work, since sub, for instance, is a symbol, not a cons. JF Rit
barmar@think.com (Barry Margolin) (03/17/90)
In article <1990Mar16.170540.20445@Neon.Stanford.EDU> rit@killdeer.stanford.edu (Jean-Francois Rit) writes: >What is an elegant solution to implement the following function: > >(defxxx with-bindings (b-list s-exprs) > "evaluates the s-exprs in an implicit progn. If the argument s-exprs contains > free variables, they are bound according to b-list. If you're programming in Common Lisp you want to use PROGV, which allows you to bind dynamic variables specified at runtime. Here's an implementation that has precisely the semantics you described. (defun with-bindings (b-list s-expr) ; from your example, it appears that ; s-expr should be singular (progv (mapcar #'first b-list) (mapcar #'second b-list) (eval s-expr))) Actually, I'd suggest implementing this as a macro to avoid the EVAL (which would allow proper lexical scoping): (defmacro with-bindings ((b-list) &body body) "Execute BODY with the special bindings specified in B-LIST in effect. B-LIST is evaluated, and should return an association list of the form ((var1 val1) (var2 val2) ...). Returns the value of the last form in BODY." (let ((b-var (gensym))) `(let ((,b-var ,b-list)) ; why doesn't CL have ONCE-ONLY? (progv (mapcar #'first ,b-var) (mapcar #'second ,b-var) .,body)))) (setq sub '((?x (1 2)) (?y (3 5))) clause '(+ (car ?x) (cadr ?y))) (with-bindings (sub) (eval clause)) => 6 In your particular example the EVAL is necessary because the clause is also computed at runtime (I presume you're implementing an interpreter of some kind, by translating into Lisp), but I think it's better not to hide it away in the implementation of WITH-BINDINGS, as it would restrict the ways in which WITH-BINDINGS could be used. I think it's better to have the EVAL out in the open. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar