From: Dan Bensen
Subject: Runtime binding computation
Date: 
Message-ID: <f2pnfq$fck$1@wildfire.prairienet.org>
I want to assign a value to a variable, but the program needs to
select the variable at runtime.  It would be snazzy if it could
compute the appropriate symbol at runtime and pass it to a function
that finds the symbol's current binding.  Is there a way to do that?
I don't see a current-symbol-binding function anywhere.
Both bindings are lexical in my current application.

-- 
Dan
www.prairienet.org/~dsb/

From: Kent M Pitman
Subject: Re: Runtime binding computation
Date: 
Message-ID: <u3b1rflzb.fsf@nhplace.com>
Dan Bensen <··········@cyberspace.net> writes:

> I want to assign a value to a variable, but the program needs to
> select the variable at runtime.  It would be snazzy if it could
> compute the appropriate symbol at runtime and pass it to a function
> that finds the symbol's current binding.  Is there a way to do that?
> I don't see a current-symbol-binding function anywhere.
> Both bindings are lexical in my current application.

The reason this isn't available is because it would mean that anyone
could write trojan horses that affected others' programs.  Lisp used
to work this way and programs were always accidentaly modifying other
programs.  It's a barrier to efficient compilation, since compilers
like to "compile away" variables. 

One fix is to make your variables special.  That's exactly what that
is for.  It says "let someone outside modify my program".  I don't
recommend doing it, though.

You probably think you want something vaguely like this.  Personally,
I don't recommend this either, since I don't think it's good coding
style in most cases.  But it is an option within your own grasp,
once you figure out how to use the tools you have...

(defmacro keyed-let (bindings &body forms)
  (let ((variable (gensym "VARIABLE"))
        (new-value (gensym "NEW-VALUE")))
    `(let ,bindings
       (flet ((keyed-value (,variable)
                (ecase ,variable
                  ,@(mapcar #'(lambda (binding)
                                (let ((var (first binding)))
                                  `((,var) ,var)))
                            bindings)))
              ((setf keyed-value) (,new-value ,variable)
                (ecase ,variable
                  ,@(mapcar #'(lambda (binding)
                                (let ((var (first binding)))
                                  `((,var) (setq ,var ,new-value))))
                            bindings))))
          ,@forms))))

(defun foo (varname newval)
  (keyed-let ((x 3) (y 4) (z))
    (setq z (+ x y))
    (print `(the value of ,varname is ,(keyed-value varname)))
    (setf (keyed-value varname) newval)
    (print `(now the value of ,varname is ,(keyed-value varname)))
    (list x y z)))

(foo 'z 13)

(THE VALUE OF Z IS 7) 
(NOW THE VALUE OF Z IS 13) 
=> (3 4 13)

(pprint
  (macroexpand-1
    '(keyed-let ((x 3) (y 4) (z))
       (setq z (+ x y))
       (print `(the value of ,varname is ,(keyed-value varname)))
       (setf (keyed-value varname) newval)
       (print `(now the value of ,varname is ,(keyed-value varname)))
       (list x y z))))

(LET ((X 3) (Y 4) (Z))
  (FLET ((KEYED-VALUE (#:VARIABLE17474)
           (ECASE #:VARIABLE17474
             ((X) X)
             ((Y) Y)
             ((Z) Z)))
         ((SETF KEYED-VALUE) (#:NEW-VALUE17475 #:VARIABLE17474)
           (ECASE #:VARIABLE17474
             ((X) (SETQ X #:NEW-VALUE17475))
             ((Y) (SETQ Y #:NEW-VALUE17475))
             ((Z) (SETQ Z #:NEW-VALUE17475)))))
    (SETQ Z (+ X Y))
    (PRINT `(THE VALUE OF ,VARNAME IS ,(KEYED-VALUE VARNAME)))
    (SETF (KEYED-VALUE VARNAME) NEWVAL)
    (PRINT `(NOW THE VALUE OF ,VARNAME IS ,(KEYED-VALUE VARNAME)))
    (LIST X Y Z)))
From: Pascal Costanza
Subject: Re: Runtime binding computation
Date: 
Message-ID: <5bbb70F2rb0kbU1@mid.individual.net>
Dan Bensen wrote:
> I want to assign a value to a variable, but the program needs to
> select the variable at runtime.  It would be snazzy if it could
> compute the appropriate symbol at runtime and pass it to a function
> that finds the symbol's current binding.  Is there a way to do that?
> I don't see a current-symbol-binding function anywhere.
> Both bindings are lexical in my current application.

There is no (portable) way to programmatically access lexical bindings. 
This allows compilers to compile away symbolic references and replace 
them with lexical addressing.

This means that you have to manage your own mappings from symbols to 
values if you want to modify them at runtime. For example, CLOS objects 
can be used here, or depending on the requirements, simple hash tables 
or even assocation lists.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Dan Bensen
Subject: Re: Runtime binding computation
Date: 
Message-ID: <f2pui8$hei$1@wildfire.prairienet.org>
Pascal Costanza wrote:
> There is no (portable) way to programmatically access lexical bindings. 
> This allows compilers to compile away symbolic references and replace 
> them with lexical addressing.

Thanks, that's what I thought.

-- 
Dan
www.prairienet.org/~dsb/
From: Pillsy
Subject: Re: Runtime binding computation
Date: 
Message-ID: <1179685838.996554.301390@a26g2000pre.googlegroups.com>
On May 20, 1:01 pm, Dan Bensen <··········@cyberspace.net> wrote:

> Pascal Costanza wrote:
> > There is no (portable) way to programmatically access lexical bindings.
> > This allows compilers to compile away symbolic references and replace
> > them with lexical addressing.

> Thanks, that's what I thought.

It just so happens that I wrote a macro to do this (relatively) nicely
the other day, with a hash table to store the values associated with
the symbols, and symbol-macrolets to make them look like any other
variables. Redefining the functions (via FLET) that are called when no
binding for a symbol can be found
allows them to emulate lexical scoping. The lexical value associated
with a symbol can be accessed with LEXICAL-VALUE, and set with (SETF
LEXICAL-VALUE).

Cheers, Pillsy

(defun get-unbound-symbol (sym)
  (error "Symbol ~S has no lexical binding!" sym))

(defun set-unbound-symbol (val sym)
  (declare (ignore val))
  (error "Symbol ~S cannot have a lexical binding!" sym))

(defmacro with-lexical-symbols (bindings &body body)
  (multiple-value-bind (vars vals)
      (loop
	 :for b :in bindings
	 :for (var val) := (if (atom b)
			       (list b)
			       b)
	 :collect var :into vars
	 :collect val :into vals
	 :finally (return (values vars vals)))
    (with-unique-names (symbol-table unbound sym val)
      `(let ((,symbol-table (make-hash-table
			     :size ,(length vars) :test #'eq)))
	 ;; Is using a hash table the way to go?
	 (mapc #'(lambda (k v)
		   (setf (gethash k ,symbol-table) v))
	       ',vars ',vals)
	 (symbol-macrolet
	     ,(mapcar #'(lambda (v)
			  `(,v (gethash ',v ,symbol-table)))
		      vars)
	   (let ((,unbound (cons nil nil)))
	     (flet ((lexical-value (,sym)
		      (let ((,val (gethash ,sym ,symbol-table ,unbound)))
			(if (eq ,val ,unbound)
			    (get-unbound-symbol ,sym)
			    ,val)))
		    ((setf lexical-value) (,val ,sym)
		      (when (eq (gethash ,sym ,symbol-table ,unbound)
				,unbound)
			(set-unbound-symbol ,val ,sym))
		     (setf (gethash ,sym ,symbol-table) ,val)))
	       (flet ((get-unbound-symbol (,sym)
			(lexical-value ,sym))
		      (set-unbound-symbol (,val ,sym)
			(setf (lexical-value ,sym) ,val)))
		,@body))))))))

(defun test-nesting-1 (s1 s2)
  (with-lexical-symbols ((a 'foo))
    (list (lexical-value s1)
	  (with-lexical-symbols ((b 'bar))
	    (lexical-value s2)))))

(defun test-nesting-2 (new1 s1 new2 s2)
  (with-lexical-symbols ((a 'foo))
    (setf (lexical-value s1) new1)
    (with-lexical-symbols ((b 'bar))
      (setf (lexical-value s2) new2)
      (list a b))))
From: Pillsy
Subject: Re: Runtime binding computation
Date: 
Message-ID: <1179686309.764979.257700@y2g2000prf.googlegroups.com>
On May 20, 2:30 pm, Pillsy <·········@gmail.com> wrote:
> On May 20, 1:01 pm, Dan Bensen <··········@cyberspace.net> wrote

Sorry, I just caught a bug right after I posted this. I tend to come
up with totally lame test cases. :-/

> (defmacro with-lexical-symbols (bindings &body body)
>   (multiple-value-bind (vars vals)
>       (loop
>          :for b :in bindings
>          :for (var val) := (if (atom b)
>                                (list b)
>                                b)
>          :collect var :into vars
>          :collect val :into vals
>          :finally (return (values vars vals)))
>     (with-unique-names (symbol-table unbound sym val)
>       `(let ((,symbol-table (make-hash-table
>                              :size ,(length vars) :test #'eq)))
>          ;; Is using a hash table the way to go?
>          (mapc #'(lambda (k v)
>                    (setf (gethash k ,symbol-table) v))
>                ',vars ',vals)

This should read

	 (mapc #'(lambda (k v)
		   (setf (gethash k ,symbol-table) v))
	       ',vars (list ,@vals))

Sorry, Pillsy

>          (symbol-macrolet
>              ,(mapcar #'(lambda (v)
>                           `(,v (gethash ',v ,symbol-table)))
>                       vars)
>            (let ((,unbound (cons nil nil)))
>              (flet ((lexical-value (,sym)
>                       (let ((,val (gethash ,sym ,symbol-table ,unbound)))
>                         (if (eq ,val ,unbound)
>                             (get-unbound-symbol ,sym)
>                             ,val)))
>                     ((setf lexical-value) (,val ,sym)
>                       (when (eq (gethash ,sym ,symbol-table ,unbound)
>                                 ,unbound)
>                         (set-unbound-symbol ,val ,sym))
>                      (setf (gethash ,sym ,symbol-table) ,val)))
>                (flet ((get-unbound-symbol (,sym)
>                         (lexical-value ,sym))
>                       (set-unbound-symbol (,val ,sym)
>                         (setf (lexical-value ,sym) ,val)))
>                 ,@body))))))))
>
> (defun test-nesting-1 (s1 s2)
>   (with-lexical-symbols ((a 'foo))
>     (list (lexical-value s1)
>           (with-lexical-symbols ((b 'bar))
>             (lexical-value s2)))))
>
> (defun test-nesting-2 (new1 s1 new2 s2)
>   (with-lexical-symbols ((a 'foo))
>     (setf (lexical-value s1) new1)
>     (with-lexical-symbols ((b 'bar))
>       (setf (lexical-value s2) new2)
>       (list a b))))
From: Kamen TOMOV
Subject: Re: Runtime binding computation
Date: 
Message-ID: <utzu7eamj.fsf@cybuild.com>
On ������, ��� 20 2007, Dan Bensen wrote:

> I want to assign a value to a variable, but the program needs to
> select the variable at runtime.  It would be snazzy if it could
> compute the appropriate symbol at runtime and pass it to a function
> that finds the symbol's current binding.  Is there a way to do that?
> I don't see a current-symbol-binding function anywhere.
> Both bindings are lexical in my current application.

(eval (find-symbol "SOME-SYMBOL")) - isn't it that what you call the
current symbol binding?

To set the symbol's value:

(set (find-symbol "SOME-SYMBOL"))


HTH,

-- 
Kamen
http://www.cybuild.com/~kat
From: Dan Bensen
Subject: Re: Runtime binding computation
Date: 
Message-ID: <f2pt36$h39$1@wildfire.prairienet.org>
>> Both bindings are lexical in my current application.

Kamen TOMOV wrote:
> (eval (find-symbol "SOME-SYMBOL")) - isn't it that what you call
> the current symbol binding?

That's the global value of the symbol's value slot.  I want
the current lexical binding.  I have a suspicion it's not
supported, but I'm not sure why.  I guess it must be that
the symbol is only used at compile time for lexical bindings,
but I thought I would ask just to make sure.

-- 
Dan
www.prairienet.org/~dsb/
From: Pascal Costanza
Subject: Re: Runtime binding computation
Date: 
Message-ID: <5bbbbsF2rb0kbU2@mid.individual.net>
Kamen TOMOV wrote:
> On ������, ��� 20 2007, Dan Bensen wrote:
> 
>> I want to assign a value to a variable, but the program needs to
>> select the variable at runtime.  It would be snazzy if it could
>> compute the appropriate symbol at runtime and pass it to a function
>> that finds the symbol's current binding.  Is there a way to do that?
>> I don't see a current-symbol-binding function anywhere.
>> Both bindings are lexical in my current application.
> 
> (eval (find-symbol "SOME-SYMBOL")) - isn't it that what you call the
> current symbol binding?
> 
> To set the symbol's value:
> 
> (set (find-symbol "SOME-SYMBOL"))

eval and set should be avoided for these purposes. symbol-value and 
(setf symbol-value) are your friends.

However, they should only be used if you are interested in taking 
advantage of the dynamic scoping that symbol values enable. Most of the 
time, you probably want lexical scoping though, and then objects or maps 
are better.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Duane Rettig
Subject: Re: Runtime binding computation
Date: 
Message-ID: <o03b1q7pnp.fsf@gemini.franz.com>
Dan Bensen <··········@cyberspace.net> writes:

> I want to assign a value to a variable, but the program needs to
> select the variable at runtime.  It would be snazzy if it could
> compute the appropriate symbol at runtime and pass it to a function
> that finds the symbol's current binding.  Is there a way to do that?
> I don't see a current-symbol-binding function anywhere.
> Both bindings are lexical in my current application.

See

http://www.lispwire.com/entry-proganal-envaccess-des

This package is mostly intended for compiler use, but the Allegro CL
interpreter is also implemented using these environments, and thus
dynamic value information can be implemented using the same interface;
it is effectively the Environments interface described in CLtL2, with a
few differences.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182