* load in environment
@ 2007-07-06 3:43 Jon Wilson
2007-07-06 4:26 ` Stephen Compall
0 siblings, 1 reply; 7+ messages in thread
From: Jon Wilson @ 2007-07-06 3:43 UTC (permalink / raw)
To: Guile Users
Hi,
I was wondering if there is a built-in way to eval the contents of a
file inside of an environment other than (current-module)? We have eval
and primitive-eval, and it seems that load is currently (conceptually) a
read, primitive-eval loop until eof is reached. Why not allow an
environment arg to load, making it (conceptually) a read, eval loop
until eof is reached?
There are two ways that I've thought of to implement this if it is not
implemented in guile already (which it doesn't seem to be). One is to
simply read the file repeatedly, and eval the results in the given
environment:
(define load-env-1 filename env)
(let* ((file (open-input-file filename))
(datum (read file)))
(while (not (eof-object? datum))
(eval datum env)
(set! datum (read file))))
The second way is to make the desired environment temporarily be the
current module:
(define load-env-2 filename env)
(let ((real-current-module (current-module)))
(set-current-module! env)
(load filename)
(set-current-module! real-current-module)))
The second way has the advantage of not reinventing the wheel when it
comes to the read-eval loop, but looks rather strange. If anyone knows
of a better way to do this, or especially if someone knows of a
procedure already in guile to do exactly this, I'd love to hear about
it. If anyone has thoughts on ways that one or both of these might be
improved, I'd also love to hear about that.
Regards,
Jon
_______________________________________________
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: load in environment
2007-07-06 3:43 load in environment Jon Wilson
@ 2007-07-06 4:26 ` Stephen Compall
2007-07-06 5:19 ` Jon Wilson
0 siblings, 1 reply; 7+ messages in thread
From: Stephen Compall @ 2007-07-06 4:26 UTC (permalink / raw)
To: Guile Users
Jon Wilson wrote:
> The second way is to make the desired environment temporarily be the
> current module:
>
> (define load-env-2 filename env)
> (let ((real-current-module (current-module)))
> (set-current-module! env)
> (load filename)
> (set-current-module! real-current-module)))
>
> The second way has the advantage of not reinventing the wheel when it
> comes to the read-eval loop, but looks rather strange.
It is a sensible enough pattern, easily made exit/reentry-safe with
dynamic-wind in Scheme:
(define (load filename . env-lst)
(if (null? env-lst)
((@ (guile) load) filename)
(load-env-2 filename (car env-lst))))
(define (load-env-2 filename env)
(let ((old-cm #f))
(dynamic-wind
(lambda ()
(set! old-cm (current-module))
(set-current-module! (environment-module env)))
(lambda () (load filename))
(lambda ()
(set-current-module! old-cm)))))
What other Guile state might you want to modify in the dynamic context
of a load, though?
--
;;; Stephen Compall ** http://scompall.nocandysw.com/blog **
But you know how reluctant paranormal phenomena are to reveal
themselves when skeptics are present. --Robert Sheaffer, SkI 9/2003
_______________________________________________
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: load in environment
2007-07-06 4:26 ` Stephen Compall
@ 2007-07-06 5:19 ` Jon Wilson
2007-07-06 6:03 ` Stephen Compall
0 siblings, 1 reply; 7+ messages in thread
From: Jon Wilson @ 2007-07-06 5:19 UTC (permalink / raw)
To: Guile Users
Stephen Compall wrote:
>
> What other Guile state might you want to modify in the dynamic context
> of a load, though?
>
Dynamic-wind looks like a quite good idea here. I'll probably use
that. Thanks.
Well, I'm writing a function to load up some data from a file and stick
it in a hash table. The data file looks something like this:
-- begin data file --
(item "foo" "bar is a metasyntactic variable" 1)
(item "baz" "barn is a unit of cross section" 2)
(item "frob" "nitz is more or less meaningless" 86)
-- end data file --
Then I call a function to load this data.
(define (load-data filename)
(let* ((my-table (make-hash-table))
(item (lambda (name text number)
(hash-set! my-table name (make-item text number))))
(m (make-module))
(real-current-module (current-module)))
(module-define! m 'item item)
(set-current-module m)
(load filename)
(set-current-module real-current-module)
my-table)))
[note: make-item is a record constructor.]
I certainly could just write code that reads in an expression from the
file, and sticks the data from it into the hash table. Probably safer
than using load (nothing is evaluated), and perhaps better for other
reasons as well. But this way is very pretty (I think). Additionally,
if I add (module-use! m (null-environment 5)) or some such, then the
user can generate the data programmatically, which sounds attractive
(there isn't currently a good use-case for this, but I can picture some
down the road perhaps).
I'm not sure if my-table is what you meant by "other guile state" that I
might want to modify, but it is definitely something visible to the rest
of the program which I want to modify by loading filename. I'm a little
bit mystified that I can modify my-table from inside (load filename) at
all, since my-table is certainly not visible to the code inside
filename. I guess that I can because my-table is wrapped up in the
closure of item. I'm not really clear on the interaction between
modules (especially set-current-module) and closures. A closure inside
of one module can apparently reference and modify things in quite
another module altogether. Maybe if it were not 1am, this would be more
obvious.
Regards,
Jon
_______________________________________________
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: load in environment
2007-07-06 5:19 ` Jon Wilson
@ 2007-07-06 6:03 ` Stephen Compall
2007-07-06 6:06 ` Jon Wilson
0 siblings, 1 reply; 7+ messages in thread
From: Stephen Compall @ 2007-07-06 6:03 UTC (permalink / raw)
To: Guile Users
Jon Wilson wrote:
> I'm not sure if my-table is what you meant by "other guile state" that I
> might want to modify, but it is definitely something visible to the rest
> of the program which I want to modify by loading filename.
I'm saying that there are many possible system properties one might want
to temporarily change when loading, so it is impractical and asymmetric
to exalt one or another as an argument to `load'.
> I'm a little
> bit mystified that I can modify my-table from inside (load filename) at
> all, since my-table is certainly not visible to the code inside
> filename. I guess that I can because my-table is wrapped up in the
> closure of item. I'm not really clear on the interaction between
> modules (especially set-current-module) and closures. A closure inside
> of one module can apparently reference and modify things in quite
> another module altogether.
Your `item' closure carries around an environment, which has as its
environment-module the module that contains your `load-data' function.
When you call it, even from another environment with a different
environment-module, you evaluate its expressions in the environment it
captured when it was created. The closure isn't "inside" any module;
you merely gave it a binding in your temporary module.
temp-module m
has #<variable ... value: #<procedure #f (name text number)>
has #<procedure #f (name text number)> which is eq? to item
captured the environment containing my-table
so can refer to my-table when called
--
;;; Stephen Compall ** http://scompall.nocandysw.com/blog **
But you know how reluctant paranormal phenomena are to reveal
themselves when skeptics are present. --Robert Sheaffer, SkI 9/2003
_______________________________________________
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: load in environment
2007-07-06 6:03 ` Stephen Compall
@ 2007-07-06 6:06 ` Jon Wilson
0 siblings, 0 replies; 7+ messages in thread
From: Jon Wilson @ 2007-07-06 6:06 UTC (permalink / raw)
To: Guile Users
Stephen Compall wrote:
> The closure isn't "inside" any module; you merely gave it a binding in
> your temporary module.
Ahhhh. You seem to have effectively defuzzied my thinking. Again, thanks!
Jon
_______________________________________________
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: load in environment
@ 2007-07-07 8:52 Marco Maggi
2007-07-09 17:22 ` Jon Wilson
0 siblings, 1 reply; 7+ messages in thread
From: Marco Maggi @ 2007-07-07 8:52 UTC (permalink / raw)
To: guile-user
"Jon Wilson" wrote:
>I'm writing a function to load up some data from a file and
>stick it in a hash table.
Lemmesee if I get it:
1. data representation is stored in a file;
2. the representation format is an Application Specific
Language (ASL), so the file is really a script in ASL;
3. ASL happens to be Scheme-like;
4. to convert the file representation in a process's
internal representation the script must be evaluatd in an
ASL interpreter;
5. nobody wants the ASL script to mess with the process'
state or, worst, mess with the file system, etc;
this can be done using pure modules.
(use-modules (ice-9 rdelim))
(define (make-asl-interp funcs)
(let ((asl-interp (make-module)))
(purify-module! asl-interp)
(for-each (lambda (p)
(module-define! asl-interp (car p) (cdr p)))
funcs)
asl-interp))
(define (asl-eval file-name)
(let* ((data-table (make-hash-table))
(item (lambda (name text number)
(hash-set! data-table name
(make-item text number))))
(asl-interp (make-asl-interp (list
(cons 'item item)))))
(with-input-from-file file-name
(lambda ()
(eval-string (read-delimited "") asl-interp)))
data-table))
;; ------------------------------------------------------------
(define make-item list)
(define table (asl-eval "data.asl"))
(format #t "dumping table:~%")
(hash-for-each (lambda (key val)
(format #t "~/key ~S, val ~S~%" key val))
table)
--
Marco Maggi
"They say jump!, you say how high?"
Rage Against the Machine - "Bullet in the Head"
_______________________________________________
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: load in environment
2007-07-07 8:52 Marco Maggi
@ 2007-07-09 17:22 ` Jon Wilson
0 siblings, 0 replies; 7+ messages in thread
From: Jon Wilson @ 2007-07-09 17:22 UTC (permalink / raw)
To: guile-user
Hi Marco,
What does PURIFY-MODULE! actually do? The docstring is just almost
clear enough for me to understand its purpose.
`purify-module!' is a procedure in the (guile) module.
Removes bindings in MODULE which are inherited from the (guile) module.
I think the mechanics of what it does are clear enough, but from my
understanding of modules, it seems essentially useless. MAKE-MODULE
returns an empty module with no bindings, which inherits from no other
module. Calling PURIFY-MODULE! on such an empty module would thus be a
no-op. The only reason that a module would inherit any bindings from
the (guile) module would be if it used (via MODULE-USE! or some such)
the guile module, whether directly, or via another module. So, if you
want a module which does not inherit any bindings from (guile), then it
seems the solution would be to simply not have your module use (guile),
or any module which uses (guile). I suppose that if you used a module
which used (guile), that it might be of some use, but presumably, the
module that uses (guile) does so for a reason, and removing those
bindings might cause it to stop working, in which case using that module
at all would be pointless. Clearly I've misunderstood something or other.
Your assessment of the situation seems to be correct. I have a
Scheme-like declarative ASL.
Is there any reason why you chose to read and eval the file manually
rather than using LOAD with the current module set to asl-interp?
Finally, I'd like to allow the user to generate the declarations in the
ASL programmatically. Naturally, this requires adding things like
lambda and + and stuff into asl-interp. How can I evaluate the safety
of various things I might add in? I'd even somewhat like to allow LOAD,
so that the ASL declarations could be split out into multiple files if
the user wanted.
Regards,
Jon
Marco Maggi wrote:
> "Jon Wilson" wrote:
>
>> I'm writing a function to load up some data from a file and
>> stick it in a hash table.
>>
>
> Lemmesee if I get it:
>
> 1. data representation is stored in a file;
> 2. the representation format is an Application Specific
> Language (ASL), so the file is really a script in ASL;
> 3. ASL happens to be Scheme-like;
> 4. to convert the file representation in a process's
> internal representation the script must be evaluatd in an
> ASL interpreter;
> 5. nobody wants the ASL script to mess with the process'
> state or, worst, mess with the file system, etc;
>
> this can be done using pure modules.
>
>
> (use-modules (ice-9 rdelim))
>
> (define (make-asl-interp funcs)
> (let ((asl-interp (make-module)))
> (purify-module! asl-interp)
> (for-each (lambda (p)
> (module-define! asl-interp (car p) (cdr p)))
> funcs)
> asl-interp))
>
> (define (asl-eval file-name)
> (let* ((data-table (make-hash-table))
> (item (lambda (name text number)
> (hash-set! data-table name
> (make-item text number))))
> (asl-interp (make-asl-interp (list
> (cons 'item item)))))
> (with-input-from-file file-name
> (lambda ()
> (eval-string (read-delimited "") asl-interp)))
> data-table))
>
> ;; ------------------------------------------------------------
>
> (define make-item list)
> (define table (asl-eval "data.asl"))
>
> (format #t "dumping table:~%")
> (hash-for-each (lambda (key val)
> (format #t "~/key ~S, val ~S~%" key val))
> table)
>
>
_______________________________________________
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-07-09 17:22 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-06 3:43 load in environment Jon Wilson
2007-07-06 4:26 ` Stephen Compall
2007-07-06 5:19 ` Jon Wilson
2007-07-06 6:03 ` Stephen Compall
2007-07-06 6:06 ` Jon Wilson
-- strict thread matches above, loose matches on Subject: below --
2007-07-07 8:52 Marco Maggi
2007-07-09 17:22 ` Jon Wilson
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).