unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Newbie question:  bind a variable on the fly
@ 2006-06-10 10:23 Vincent De Groote
  0 siblings, 0 replies; 6+ messages in thread
From: Vincent De Groote @ 2006-06-10 10:23 UTC (permalink / raw)


Hello,

Is there a way to catch an "unbound-variable" exception, bind the
variable on the fly, and continue execution as if the exception didn't
occurs ?

I'd like to catch this exception in a c function:  the exception context
should be available, to retrieve the variable or function name.  This
handler will lookup the value in a relational database.

Is this possible ?  


Thanks for you replies

Vincent De Groote




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


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

* Newbie question:  bind a variable on the fly
@ 2006-06-10 10:25 Vincent De Groote
  2006-06-10 13:08 ` Marius Vollmer
  2006-06-11 17:42 ` Jon Wilson
  0 siblings, 2 replies; 6+ messages in thread
From: Vincent De Groote @ 2006-06-10 10:25 UTC (permalink / raw)


Hello,

Is there a way to catch an "unbound-variable" exception, bind the
variable on the fly, and continue execution as if the exception didn't
occurs ?

I'd like to catch this exception in a c function:  the exception context
should be available, to retrieve the variable or function name.  This
handler will lookup the value in a relational database.

Is this possible ?  


Thanks for you replies

Vincent De Groote



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


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

* Re: Newbie question:  bind a variable on the fly
  2006-06-10 10:25 Newbie question: bind a variable on the fly Vincent De Groote
@ 2006-06-10 13:08 ` Marius Vollmer
  2006-06-11 17:42 ` Jon Wilson
  1 sibling, 0 replies; 6+ messages in thread
From: Marius Vollmer @ 2006-06-10 13:08 UTC (permalink / raw)
  Cc: guile-user

Vincent De Groote <vincent.degroote@win.be> writes:

> Is there a way to catch an "unbound-variable" exception, bind the
> variable on the fly, and continue execution as if the exception didn't
> occurs ?

No, unfortunately not (but read on below for an alternative solution
that doesn't use exceptions).  Guile's exception system does not offer
'restarts' as Common Lisp does, for example.  That is, after an error
has been signalled in a computation, there is no way to resume the
computation after handling the error.

> I'd like to catch this exception in a c function: the exception
> context should be available, to retrieve the variable or function
> name.  This handler will lookup the value in a relational database.

You can create a special module that will do the database lookups when
variables are looked up.  This requires using using the low-level
module API, tho, which is unfortunately not that well supported at the
moment.  It definitely is not 'newbie' territory.

If that didn't scare you away successfully, here is an example of how
you might do it:

    (define (lazy-binder mod sym def?)
      (pk 'lazy sym def?)
      (let ((var (case sym
                   ((foo)
                    (make-variable 1))
                   ((bar)
                    (make-variable 2))
                   (else
                    #f))))
        (if var
            (module-add! mod sym var))
        var))

    ;; This otherwise useless call will memoize the 'failure-path' of the
    ;; lazy-binder and prevent infinite loops when it is used to lookup
    ;; the variables it uses itself.  This should not really happen
    ;; because the lazy-binder is used last (see below), but Guile also
    ;; looks up syntactic keywords like 'else' and only treats them as
    ;; keywords when they are not defined.  Thus, lazy-binder must be able
    ;; to return false for 'else' without causing 'else' to be looked
    ;; up...
    ;;
    (lazy-binder #f #f #f)

    (define module (make-module 31 '() lazy-binder))

    (set-module-uses! (current-module)
                      (append (module-uses (current-module))
                              (list module)))

    (pk (+ foo bar))

    (set! foo (1+ foo))

    (pk (+ foo bar))

The longish comment is another warning that crazy things might happen
when one messes with variable lookup.

Also, something that is probably important for your application is
that the module system (and the Guile evaluator itself) only allows
you too control the lookup of variables; once a variable has been
found, it is treated as any other variable and you don't get to run
code of your own each time it is accessed.  Thus, if you want to run a
SQL query each time a variable is read, or want to update the database
when the variable is set, you are out of luck, unfortunately.

If you want that, you might want to look at a more formal approach
using explicit declaration of which identifiers are supposed to refer
to the database.  Like

    (with-db-vars (foo bar)
      (set! (foo) (+ (foo) (bar))))

which could expand into something like

    (let ((foo (make-db-var 'foo))
          (bar (make-db-var 'bar)))
      (set! (foo) (+ (foo) (bar))))

using

    (define (make-db-var sym)
      (make-procedure-with-setter 
        (lambda () (db-ref 'foo))
        (lambda (val) (db-set! 'foo val))))

You could also look into "symbol macros" which allow you to do the
same thing without having to surround every use of 'foo' with
parentheses.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


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


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

* Re: Newbie question:  bind a variable on the fly
  2006-06-10 10:25 Newbie question: bind a variable on the fly Vincent De Groote
  2006-06-10 13:08 ` Marius Vollmer
@ 2006-06-11 17:42 ` Jon Wilson
  2006-06-12 22:17   ` Neil Jerram
  1 sibling, 1 reply; 6+ messages in thread
From: Jon Wilson @ 2006-06-11 17:42 UTC (permalink / raw)
  Cc: guile-user

Hi Vincent,
Don't try this just yet.  I want other people to give it a look-over and 
make sure it isn't foolish and dangerous before anybody lets it out in the 
wild.


This doesn't use the exception, and it doesn't use a c function, and it 
doesn't do database lookups.  However, it can be used anywhere (inside lets 
and lambdas) to set! a variable that hasn't been defined.  It defines the 
variable at top level, and then sets it wherever you are.  Note: it does 
establish a global binding rather than a local binding.  This may or may 
not be what you want.  I think that using this to establish a local binding 
would be an extremely difficult thing to do, as well as probably a bad idea.

(define-macro (dyn-set! var val)
               `(begin (if (not (defined? (quote ,var)))
                         (primitive-eval `(define ,(quote ,var) #f)))
                       (set! ,var ,val)))

(defined? 'undefined-symbol) ; => #f
;(set! undefined-symbol #t)  Gives an error.
(dyn-set! undefined-symbol #t) ; No error.
(defined? 'undefined-symbol) ; => #t

Regards,
Jon

Vincent De Groote wrote:
> Hello,
> 
> Is there a way to catch an "unbound-variable" exception, bind the
> variable on the fly, and continue execution as if the exception didn't
> occurs ?
> 
> I'd like to catch this exception in a c function:  the exception context
> should be available, to retrieve the variable or function name.  This
> handler will lookup the value in a relational database.
> 
> Is this possible ?  
> 
> 
> Thanks for you replies
> 
> Vincent De Groote
> 
> 
> 
> _______________________________________________
> Guile-user mailing list
> Guile-user@gnu.org
> http://lists.gnu.org/mailman/listinfo/guile-user


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


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

* Re: Newbie question:  bind a variable on the fly
  2006-06-11 17:42 ` Jon Wilson
@ 2006-06-12 22:17   ` Neil Jerram
  2006-06-13 18:26     ` Jonathan Wilson
  0 siblings, 1 reply; 6+ messages in thread
From: Neil Jerram @ 2006-06-12 22:17 UTC (permalink / raw)
  Cc: guile-user

Jon Wilson <j85wilson@fastmail.fm> writes:

> (define-macro (dyn-set! var val)
>                `(begin (if (not (defined? (quote ,var)))
>                          (primitive-eval `(define ,(quote ,var) #f)))
>                        (set! ,var ,val)))
>
> (defined? 'undefined-symbol) ; => #f
> ;(set! undefined-symbol #t)  Gives an error.
> (dyn-set! undefined-symbol #t) ; No error.
> (defined? 'undefined-symbol) ; => #t

I think this mostly does what you want, but

- isn't ,(quote xxx) equivalent to just xxx?

- as you kind of said, it will go wrong if ,var is defined locally:
  defined? will be #f for a local variable, so a top-level variable
  with the same name will be created, but the set! will then set the
  local variable.

Regards,
    Neil



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


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

* Re: Newbie question:  bind a variable on the fly
  2006-06-12 22:17   ` Neil Jerram
@ 2006-06-13 18:26     ` Jonathan Wilson
  0 siblings, 0 replies; 6+ messages in thread
From: Jonathan Wilson @ 2006-06-13 18:26 UTC (permalink / raw)


Hi Neil,

Neil Jerram wrote:
> Jon Wilson <j85wilson@fastmail.fm> writes:
>>(define-macro (dyn-set! var val)
>>               `(begin (if (not (defined? (quote ,var)))
>>                         (primitive-eval `(define ,(quote ,var) #f)))
>>                       (set! ,var ,val)))
>>
>>(defined? 'undefined-symbol) ; => #f
>>;(set! undefined-symbol #t)  Gives an error.
>>(dyn-set! undefined-symbol #t) ; No error.
>>(defined? 'undefined-symbol) ; => #t
> 
> 
> - isn't ,(quote xxx) equivalent to just xxx?

You'd think so.  But it didn't wind up working out that way.  Try it and
see.  Perhaps this is a bug?  I suspect not, however, what with having
the nested quasiquotes, with one of them inside the primitive-eval.

I'm afraid I don't 100% understand just what I wrote...  With the nested
quasiquotes here, just what gets expanded when?  I guess that

(dyn-set! yyz 5)

becomes (under the macro expansion)

(begin (if (not (defined? 'yyz)))
          (primitive-eval `(define ,(quote yyz) #f)))
        (set! yyz 5)))

And then the other quasiquote gets expanded to
(define yyz #f)

But, I'm not quite sure why this should work this way.  It seems like
the first expansion should be

(begin (if (not (defined? 'yyz)))
          (primitive-eval `(define ,var #f)))
        (set! yyz 5)))

But in this expression, is var still bound to yyz?  It seems like this
expansion shouldn't work, we should get a "symbol var is undefined" sort
of error.  But we don't.

> 
> - as you kind of said, it will go wrong if ,var is defined locally:
>   defined? will be #f for a local variable, so a top-level variable
>   with the same name will be created, but the set! will then set the
>   local variable.

Ah yes, that is an important twist I hadn't thought of.  Is there a
`local-defined?' function anywhere?

Also, I found myself completely unable to bind this macro to the symbol
set!, even by strange things like defining real-set! to be set!, and
then defining the macro, and then (real-set! set! dyn-set!).  Bad things
happened to my poor abused guile.

Thanks for taking a look!

Regards,
Jon



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


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

end of thread, other threads:[~2006-06-13 18:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-10 10:25 Newbie question: bind a variable on the fly Vincent De Groote
2006-06-10 13:08 ` Marius Vollmer
2006-06-11 17:42 ` Jon Wilson
2006-06-12 22:17   ` Neil Jerram
2006-06-13 18:26     ` Jonathan Wilson
  -- strict thread matches above, loose matches on Subject: below --
2006-06-10 10:23 Vincent De Groote

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).