unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Injecting variables into closures.
@ 2007-11-29 14:04 Kjetil S. Matheussen
  2007-11-29 14:44 ` Kjetil S. Matheussen
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Kjetil S. Matheussen @ 2007-11-29 14:04 UTC (permalink / raw)
  To: guile-user


Hi,

I need (well) to inject variables into closures, and have
come up with the following macro to do so:

(define-macro (inject-variable name value)
   (define env (gensym))
   (define closure (gensym))
   (define vars (gensym))
   (define secondname (gensym))
   (define secondval (gensym))
   (define first-env (gensym))
   `((procedure->macro (lambda (,(gensym) ,env)
                         (cond ((null? (cdr ,env))
                                (let ((,closure (car ,env)))
                                  (set-car! ,env (cons ',name ,value))
                                  (set-cdr! ,env (list ,closure))))
                               ((null? (null? (cdr (car ,env))))
                                (let* ((,vars (car ,env))
                                       (,secondname (car vars))
                                       (,secondval (cdr vars)))
                                  (set-car! ,env
                                            (list (list ',name firstname)
                                                  ,value ,secondval))))
                               (else
                                (let ((,first-env (car ,env)))
                                  (set-cdr! ,first-env
                                            (cons ,value (cdr ,first-env)))
                                  (set-car! ,first-env
                                            (cons ',name (car ,first-env)))
                                  (set-car! ,env ,first-env))))))))


(let ()
   (display (defined? 'gakk))
   (inject-variable gakk 90)
   gakk)
=> #f90


Now I wonder, is this safe and portable? Or are there
other and better ways to do this?

Thanks for any answers.

Kjetil.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
  2007-11-29 14:04 Injecting variables into closures Kjetil S. Matheussen
@ 2007-11-29 14:44 ` Kjetil S. Matheussen
  2007-11-29 14:54 ` Kjetil S. Matheussen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Kjetil S. Matheussen @ 2007-11-29 14:44 UTC (permalink / raw)
  To: Kjetil S. Matheussen; +Cc: guile-user



On Thu, 29 Nov 2007, Kjetil S. Matheussen wrote:

>
> Hi,
>
> I need (well) to inject variables into closures, and have
> come up with the following macro to do so:
>
> (define-macro (inject-variable name value)
...
>                         (cond ((null? (cdr ,env))
...
>                               ((null? (null? (cdr (car ,env))))


#@^%$^&#!


(define-macro (inject-variable name value)
   (define env (gensym))
   (define closure (gensym))
   (define vars (gensym))
   (define secondname (gensym))
   (define secondval (gensym))
   (define first-env (gensym))
   `((procedure->macro
      (lambda (,(gensym) ,env)
        (define ,first-env (car ,env))
        (cond ((null? (cdr ,env))
 	      (let ((,closure ,first-env))
 		(set-car! ,env (cons ',name ,value))
 		(set-cdr! ,env (list ,closure))))
 	     ((not (pair? (cdr ,first-env)))
 	      (let* ((,vars ,first-env)
 		     (,secondname (car ,vars))
 		     (,secondval (cdr ,vars)))
 		(set-car! ,env
 			  (list (list ',name ,secondname)
 				,value ,secondval))))
 	     (else
 	      (set-cdr! ,first-env
 			(cons ,value (cdr ,first-env)))
 	      (set-car! ,first-env
 			(cons ',name (car ,first-env)))
 	      (set-car! ,env ,first-env)))))))


Sorry. :-)



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
  2007-11-29 14:04 Injecting variables into closures Kjetil S. Matheussen
  2007-11-29 14:44 ` Kjetil S. Matheussen
@ 2007-11-29 14:54 ` Kjetil S. Matheussen
  2007-11-29 16:02   ` Ludovic Courtès
       [not found] ` <877ik1dpyj.fsf@unknownlamer.org>
  2007-11-29 15:53 ` Ludovic Courtès
  3 siblings, 1 reply; 7+ messages in thread
From: Kjetil S. Matheussen @ 2007-11-29 14:54 UTC (permalink / raw)
  To: guile-user, guile-devel



On Thu, 29 Nov 2007, Kjetil S. Matheussen wrote:

>
> (let ()
>   (display (defined? 'gakk))
>   (inject-variable gakk 90)
>   gakk)
> =>  #f90
>

By the way. I'm quite surprised the environments consist
of linked lists. Wouldn't it be much faster using hash
tables instead? Perhaps the variables are cached or something?




_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
       [not found] ` <877ik1dpyj.fsf@unknownlamer.org>
@ 2007-11-29 15:52   ` Kjetil S. Matheussen
  0 siblings, 0 replies; 7+ messages in thread
From: Kjetil S. Matheussen @ 2007-11-29 15:52 UTC (permalink / raw)
  To: Clinton Ebadi, guile-user



On Thu, 29 Nov 2007, Clinton Ebadi wrote:

> "Kjetil S. Matheussen" <k.s.matheussen@notam02.no> writes:
>
>> Hi,
>>
>> I need (well) to inject variables into closures, and have
>> come up with the following macro to do so:
>>
>> (define-macro (inject-variable name value)
>>   (define env (gensym))
>>   (define closure (gensym))
>>   (define vars (gensym))
>>   (define secondname (gensym))
>>   (define secondval (gensym))
>>   (define first-env (gensym))
>>   `((procedure->macro (lambda (,(gensym) ,env)
>>                         (cond ((null? (cdr ,env))
>>                                (let ((,closure (car ,env)))
>>                                  (set-car! ,env (cons ',name ,value))
>>                                  (set-cdr! ,env (list ,closure))))
>>                               ((null? (null? (cdr (car ,env))))
>>                                (let* ((,vars (car ,env))
>>                                       (,secondname (car vars))
>>                                       (,secondval (cdr vars)))
>>                                  (set-car! ,env
>>                                            (list (list ',name firstname)
>>                                                  ,value ,secondval))))
>>                               (else
>>                                (let ((,first-env (car ,env)))
>>                                  (set-cdr! ,first-env
>>                                            (cons ,value (cdr ,first-env)))
>>                                  (set-car! ,first-env
>>                                            (cons ',name (car ,first-env)))
>>                                  (set-car! ,env ,first-env))))))))
>>
>>
>> (let ()
>>   (display (defined? 'gakk))
>>   (inject-variable gakk 90)
>>   gakk)
>> => #f90
>>
>>
>> Now I wonder, is this safe and portable? Or are there
>> other and better ways to do this?
>
> Manipulating the environment is not going to be portable or safe. In

Well, it doesn't have to be. But I understand very well why
its not. :-)



> addition procedure->macro should be deprecated (but appears not to
> be?), and will be removed (necessarily) whenever someone finishes the
> phase separation in the evaluator.
>

Hope its not going to be. Its a convenient function.



> Is there a special reason to inject a value into the environment
> rather than let binding it?
>

I'm just playing with making a prettier module system:

(define-namespace bank)

(def-bank sum 0)
(def-bank (inc n)
   (inc! sum n))
(def-bank (dec n)
   (inc sum (- n)))

(bank/inc 50)
(bank/sum)
=> 50


I can also do it by doing a complete source transformations,
replacing sum with bank/sum everywhere and so on, but I would
rather avoid doing that.

Its just for fun.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
  2007-11-29 14:04 Injecting variables into closures Kjetil S. Matheussen
                   ` (2 preceding siblings ...)
       [not found] ` <877ik1dpyj.fsf@unknownlamer.org>
@ 2007-11-29 15:53 ` Ludovic Courtès
  3 siblings, 0 replies; 7+ messages in thread
From: Ludovic Courtès @ 2007-11-29 15:53 UTC (permalink / raw)
  To: guile-user

Hi,

"Kjetil S. Matheussen" <k.s.matheussen@notam02.no> writes:

> Now I wonder, is this safe and portable? Or are there
> other and better ways to do this?

Neither `define-macro' nor `procedure->macro' is portable: both are
Guile-specific (SCM may have similar forms, though).

Another, simpler, Guile-specific way to do this would be:

  (module-define! (current-module) 'gakk 'some-value)

There's no R[56]RS-portable way to do this AFAIK.

Thanks,
Ludovic.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
  2007-11-29 14:54 ` Kjetil S. Matheussen
@ 2007-11-29 16:02   ` Ludovic Courtès
  0 siblings, 0 replies; 7+ messages in thread
From: Ludovic Courtès @ 2007-11-29 16:02 UTC (permalink / raw)
  To: guile-user; +Cc: guile-devel

Hi,

"Kjetil S. Matheussen" <k.s.matheussen@notam02.no> writes:

> By the way. I'm quite surprised the environments consist
> of linked lists. Wouldn't it be much faster using hash
> tables instead? Perhaps the variables are cached or something?

Yes, variable references are "cached" ("memoized") so that actual
variable lookup occurs only once.  So, for instance, in the following
piece of code:

  (let ((x 1)(y 2))
    (foo y))

the reference to "y" in "(foo y)" is replaced by an "iloc" that says
"this is a reference to the second variable in the first frame".  When
that iloc is encountered, the variable's value is fetched by doing
(roughly) two `list-ref's: one to get the frame and then one to get the
variable within the frame.

Clearly, a vector-like data structure (i.e., with O(1) access to
individual elements) would help here.

Thanks,
Ludovic.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Injecting variables into closures.
       [not found] <cmu-lmtpd-10256-1196356001-0@mail-imap2.uio.no>
@ 2007-11-29 18:43 ` Kjetil S. Matheussen
  0 siblings, 0 replies; 7+ messages in thread
From: Kjetil S. Matheussen @ 2007-11-29 18:43 UTC (permalink / raw)
  To: guile-user; +Cc: ludo


Ludovic Court?s:
>
> Hi,
>
> "Kjetil S. Matheussen" <k.s.matheussen@notam02.no> writes:
>
>> Now I wonder, is this safe and portable? Or are there
>> other and better ways to do this?
>
> Neither `define-macro' nor `procedure->macro' is portable: both are
> Guile-specific (SCM may have similar forms, though).
>

Thanks, but by "portable", I did (of course) mean portable
across various versions of Guile, not any of the scheme
standards...


> Another, simpler, Guile-specific way to do this would be:
>
>  (module-define! (current-module) 'gakk 'some-value)
>

Thanks, but that's probably not enough for what I
want to do. I need to simulate dynamic scoping
somehow, and I think its only possible to do that
by manipulating the environment. But I'm not
going to do that if its going to break with
forthcoming releases of Guile.



_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-11-29 18:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-29 14:04 Injecting variables into closures Kjetil S. Matheussen
2007-11-29 14:44 ` Kjetil S. Matheussen
2007-11-29 14:54 ` Kjetil S. Matheussen
2007-11-29 16:02   ` Ludovic Courtès
     [not found] ` <877ik1dpyj.fsf@unknownlamer.org>
2007-11-29 15:52   ` Kjetil S. Matheussen
2007-11-29 15:53 ` Ludovic Courtès
     [not found] <cmu-lmtpd-10256-1196356001-0@mail-imap2.uio.no>
2007-11-29 18:43 ` Kjetil S. Matheussen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).