This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: The GIMP! By gum, I forgot all about it!



la@iki.fi writes:
> On Thu, Oct 29, 1998 at 11:10:34AM -0500, it occurred to Maciej Stachowiak to write:
> > 
> > scott@poverty.bloomington.in.us writes:
> > > Last I heard Lauri was swearing at how hard it was to emulate SIOD's
> > > braindead set! semantics in guile.
> > 
> > What does SIOD do with set! that's so unusual?
> 
> ;; SIOD's set! is really screwed up. If the variable being set is
> ;; unbound, it is bound at the top level. Otherwise it is reset. So we
> ;; have to find out if a variable is bound in a _local_ environment.. thus
> ;; we create the syntax manually. Also, SIOD set! returns the new value.
> 
> ;; There would be no prob otherwise, but all scripts use these "features"..
> 

Yuck! If gimple supports these semantics can you relagate it to a
compatibility mode, so people can be weaned off of depending on that?


> (define set! 
>   ; we memoize the correct place for the variable..
>   (procedure->memoizing-macro
>    (lambda (exp env)
>      (define variable (cadr exp))
>      (define value (caddr exp))
>      `(begin 
>         (,@(let loop ((e env))
>              (define frame (car e))
>              (cond ((procedure? frame)
>                     ; here we create the top level binding
>                     `(',variable-set! ',(frame variable #t)))
>                    ((eq? (car frame) variable)
>                     `(set-cdr! ',frame))
>                    ((and (list? (car frame)) (list-index (car frame) variable))
>                     => (lambda (i)
>                          `(',set-car! ',(list-tail (cdr frame) i))))
>                    (else (loop (cdr e)))))
>          ,value)
>         ,variable))))
> 
> 
> Yes, this is hyper-kludgy. I don't know if this even works with latest
> guile. Cleaner solutions welcome. :)
> 

How about:

(define %set! set!)

(defmacro set! (name value)
  `(begin	
     (if `(catch 'misc-error
		 (lambda ()
		   ,name
		   #t)
		 (lambda args #f))
	 (%set! ,name ,value)
	 (module-define! (current-module) ',name ,value))
     ,name))


Not the cleanest thing in the world, but it beats walking the
environment frames by hand.

There are some negative performance implications to doing the test to
see whether the variable is bound, but I am not sure this can be
avoided while still achieving SIOD semantics because guile has
`undefine'. 

 - Maciej