[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Req for help on objects and environments

From: Andy Wingo
Subject: Re: Req for help on objects and environments
Date: Fri, 03 Sep 2004 19:46:49 +0100

Hi Alp,

I know you've got a lot of answers already, but I think the environment
question is still not covered.

On Wed, 2004-09-01 at 11:28 +0300, Alp Öztarhan wrote:
> First, I want to play with the properties on objects.
> I want to be able to serialize an object along with its properties.
> I *can* make and retrieve properties of objects by use of
> (make-object-property). But how do I get a list of the properties of a
> given object?

In case you didn't figure it out, you can't, except from C with

> Second, I want to manipulate the environment in eval.
> I could not even do what the documentation tells.
> I could not get a handle on (null-environment) etc. (undefined symbol
> :-(
> Besides, I want to manipulate it, giving extra symbols etc.
> Could anybody give me any hint on these?

Sure. Scheme actually has two kinds of environments: toplevel and
lexical. The first is a simple association of names and values. The
concept is very similar to that of "modules", so in guile, toplevel
environments *are* modules[0]:

        (module? (null-environment 5)) => #t

By default, guile is not r5rs-compliant when it loads up. I think this
is because (ice-9 syncase) is very slow to load up. Anyway, using
(ice-9 r5rs) will give you everything in the report, including

Modules are what can be passed as the second argument to `eval'. They
should be accessed only with documented functions for maximum
portability between guile versions, and to other schemes. Unfortunately,
modules expose their guts too much because everyone sees boot-9.scm.

So, to opaquely add a:=5 to a module, you can say:

        (define env (null-environment 5))
        (eval '(define a 5) env)
        (eval 'a env) => 5

If you feel more dangerous, you can use module-define, module-defined?,
module-ref, module-variable, etc. See boot-9.scm for more. Dunno what
Marius thinks about this, but I like first-class modules :)

[0] This is complicated by the existence of environment SMOBs, from
environments.c / environment-*. I have no idea whether this code is on
the way in, or the way out. Marius, Dirk?

Lexical environments are a different beast. You cannot access them with
r5rs, I don't think. However, with guile you can, although it's
definitely not documented. I tried to be less hacky with the following
macro, but define-macro's memoizing behaviour caused guile 1.6 to
segfault, so I had to use low-level macros:

(define make-environment
   (lambda (exp env)
     (local-eval `(let* ,(let lp ((in (cdr exp)) (out '()))
                           (if (null? in)
                               (reverse out)
                               (lp (cddr in) (cons
                                              (list (car in) (cadr in)) 

;; e.g.
(make-environment a 5 b 6 c a)
=> <a lexical environment with a=5, b=6, c=5

This environment is created with let*, so later bindings can access the
values of previous ones. `the-environment' is a syntax that returns the
current lexical environment. local-eval is a form of eval that takes a
lexical environment instead of a toplevel. Indeed, the `env' argument to
a low-level macro is a lexical environment.


(define-macro (with-environment env . body)
    ,(list 'quote `(begin ,@body))

(with-environment (make-environment a 5)
   a) => 5

(define (bind sym val env)
  (if (defined? sym env)
      (begin (local-eval `(set! ,sym ',val) env)
      (local-eval `(let ((,sym ,val)) (the-environment)) env)))

There's more in (soundscrape environments), in my arch repository. I
wrote this when I just started with guile; the pattern of lexical
environments applied to a problem I had. Now I worry about the low-level
access. A problem for later, I guess...

Hope that helped,
Andy Wingo <address@hidden>

reply via email to

[Prev in Thread] Current Thread [Next in Thread]