unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* A plea for local-eval in 2.0.4
@ 2012-01-12 21:43 Mark H Weaver
  2012-01-12 23:02 ` Bruce Korb
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Mark H Weaver @ 2012-01-12 21:43 UTC (permalink / raw)
  To: guile-devel

I'd like to make one last plea to include my simple `local-eval'
implementation in 2.0.4.  My hope is that if we can ship it soon enough,
versions of Guile without `local-eval' will be rare enough to enable
Lilypond to eliminate their ugly hacks and simply declare that Guile
2.0.0-2.0.3 are unsupported.

However, I fear that if `local-eval' is not included in 2.0.4, then
Lilypond will have to include their ugly hacks for several more years at
least, causing Lilypond developers (and others who look at the code) to
have a rather low opinion of Guile.

I worked very hard to produce a simple and maintainable implementation
of `local-eval' in time for 2.0.4, so that we might rectify this
unfortunate Lilypond unhappiness.  It would be a shame if that work were
wasted.

     Mark



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

* Re: A plea for local-eval in 2.0.4
  2012-01-12 21:43 A plea for local-eval in 2.0.4 Mark H Weaver
@ 2012-01-12 23:02 ` Bruce Korb
  2012-01-13  9:20 ` David Kastrup
  2012-01-14 15:24 ` Andy Wingo
  2 siblings, 0 replies; 17+ messages in thread
From: Bruce Korb @ 2012-01-12 23:02 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

On 01/12/12 13:43, Mark H Weaver wrote:
> I worked very hard to produce a simple and maintainable implementation
> of `local-eval' in time for 2.0.4, so that we might rectify this
> unfortunate Lilypond unhappiness.  It would be a shame if that work were
> wasted.

Just for the record, I'm okay with taking a little extra time for this also.
My worry was over months of delay.  I, too, must disable 2.0.0 thru 2.0.3
for use with my toy.  Cheers - Bruce



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

* Re: A plea for local-eval in 2.0.4
  2012-01-12 21:43 A plea for local-eval in 2.0.4 Mark H Weaver
  2012-01-12 23:02 ` Bruce Korb
@ 2012-01-13  9:20 ` David Kastrup
  2012-01-13 16:21   ` Mark H Weaver
  2012-01-14 15:24 ` Andy Wingo
  2 siblings, 1 reply; 17+ messages in thread
From: David Kastrup @ 2012-01-13  9:20 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> I'd like to make one last plea to include my simple `local-eval'
> implementation in 2.0.4.  My hope is that if we can ship it soon enough,
> versions of Guile without `local-eval' will be rare enough to enable
> Lilypond to eliminate their ugly hacks and simply declare that Guile
> 2.0.0-2.0.3 are unsupported.

We won't be able to declare this anytime soon, but it would likely be
feasible to include a fallback implementation.  It would make little
sense to include a fallback that differs from 2.0.4 however.

I am still fuzzy on what local-eval will do when the current module at
the time of the-environment is different from that at the time of
local-eval.

Since the current module, even if nominally the same, can contain
different variables at the time of local-eval, my take on that would be
to not make it part of the environment at all.  That is, everything that
is not reachable through local scopes is not part of the environment.

While this would indeed be the most convenient option with regard to the
LilyPond case, I think that other options make less sense in general (or
cause semantics that do more harm than help).

Note that I have not actually checked what Guilev1 does here with regard
to the-environment.  If we reconstitute its use, I'll probably set the
module explicitly in the argument of the local-eval call if it turns out
to be necessary.

> I worked very hard to produce a simple and maintainable implementation
> of `local-eval' in time for 2.0.4, so that we might rectify this
> unfortunate Lilypond unhappiness.  It would be a shame if that work
> were wasted.

As I said, we won't get around catering for 2.0-2.0.3 manually for quite
a while.  But I would not want to be doing this with code different from
what shall end up in Guile eventually.

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-13  9:20 ` David Kastrup
@ 2012-01-13 16:21   ` Mark H Weaver
  2012-01-13 18:50     ` David Kastrup
  0 siblings, 1 reply; 17+ messages in thread
From: Mark H Weaver @ 2012-01-13 16:21 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:
> I am still fuzzy on what local-eval will do when the current module at
> the time of the-environment is different from that at the time of
> local-eval.

(the-environment) saves the module (where it is textually located) in
the lexical environment object.  If (the-environment) was passed to
`eval', that's the module specified by `eval's second parameter.  If
(the-environment) was passed to `primitive-eval', then that's the
(current-module) at the time primitive-eval was called.

`local-eval' passes the saved module to `eval', which temporarily
restores it (using dynamic-wind) as the current module during both macro
expansion and evaluation of the local expression.  `local-compile'
passes the saved module as the #:env parameter to `compile', which has
the same effect as for `local-eval'.

> since the current module, even if nominally the same, can contain
> different variables at the time of local-eval, my take on that would be
> to not make it part of the environment at all.  That is, everything that
> is not reachable through local scopes is not part of the environment.

I heartily disagree.  A module is conceptually part of every lexical
environment evaluated within that module.  That this makes sense is
particularly evident in the case of recursively defined top-level
procedures.  For example, in

  (define (factorial n)
    (if (zero? n) 1 (* n (factorial (- n 1)))))

it would be crazy for any lexical variable "search path" starting from
within the definition of `factorial' to lead anywhere other than the
module where this definition was evaluated, i.e. where the top-level
`factorial' was bound.

   Thanks,
     Mark



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

* Re: A plea for local-eval in 2.0.4
  2012-01-13 16:21   ` Mark H Weaver
@ 2012-01-13 18:50     ` David Kastrup
  2012-01-14  1:07       ` Mark H Weaver
  0 siblings, 1 reply; 17+ messages in thread
From: David Kastrup @ 2012-01-13 18:50 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> David Kastrup <dak@gnu.org> writes:
>> I am still fuzzy on what local-eval will do when the current module at
>> the time of the-environment is different from that at the time of
>> local-eval.
>
> (the-environment) saves the module (where it is textually located) in

What does "where it is textually located" mean?

> the lexical environment object.  If (the-environment) was passed to
> `eval', that's the module specified by `eval's second parameter.
>
> If (the-environment) was passed to `primitive-eval', then that's the
> (current-module) at the time primitive-eval was called.
>
> `local-eval' passes the saved module to `eval', which temporarily
> restores it (using dynamic-wind) as the current module during both
> macro expansion and evaluation of the local expression.
> `local-compile' passes the saved module as the #:env parameter to
> `compile', which has the same effect as for `local-eval'.

>> since the current module, even if nominally the same, can contain
>> different variables at the time of local-eval, my take on that would
>> be to not make it part of the environment at all.  That is,
>> everything that is not reachable through local scopes is not part of
>> the environment.
>
> I heartily disagree.  A module is conceptually part of every lexical
> environment evaluated within that module.

What does "evaluated within a module" mean?  For me, a module provides
the fallback for everything that can't be resolved at local scope.
Basically, it is relevant for everything that "tops out" at top level.

Now the point of local-eval is that we are evaluating in a different
context than the original one.  As opposed to the variables bound in any
given lexical scope defined by its source positions, the module-level
bindings are non-constant and can change between the-environment and
local-eval.  So they are not quite at the same level.

> That this makes sense is particularly evident in the case of
> recursively defined top-level procedures.  For example, in
>
>   (define (factorial n)
>     (if (zero? n) 1 (* n (factorial (- n 1)))))
>
> it would be crazy for any lexical variable "search path" starting from
> within the definition of `factorial' to lead anywhere other than the
> module where this definition was evaluated, i.e. where the top-level
> `factorial' was bound.

(define (factorial n)
  (if (zero? n) 1 (* n (factorial (- n 1)))))

(eval `(,factorial 5) (resolve-module '(none)))

This works actually fine since apparently the "factorial" inside of the
function is bound to the actual variable of the module.  It is _not_
bound to the _value_ of the variable: if you subsequently redefine
factorial while saving a copy, calling the copy will in the recursion
call the redefinition.

However, I would have expected if I now do
(define sob factorial)
(module-remove! (current-module) factorial)
that the variable gets removed from the module but stays operative.  It
turns out that this is not the case:

guile> (define sob factorial)
guile> (module-remove! (current-module) 'factorial)
#f
guile> (factorial 3)

Backtrace:
In current input:
  25: 0* (factorial 3)

<unnamed port>:25:1: In expression (factorial 3):
<unnamed port>:25:1: Unbound variable: factorial
ABORT: (unbound-variable)
guile> (sob 3)

Backtrace:
In current input:
  26: 0* [factorial 3]
  22: 1  (if (zero? n) 1 (* n (factorial (- n 1))))
  22: 2  [* 3 ...
  22: 3*  (factorial (- n 1))

<unnamed port>:22:24: In expression (factorial (- n 1)):
<unnamed port>:22:24: Unbound variable: factorial
ABORT: (unbound-variable)
guile> (define factorial 'huh)
guile> (sob 3)

Backtrace:
In current input:
  28: 0* [factorial 3]
  22: 1  (if (zero? n) 1 (* n (factorial (- n 1))))
  22: 2  [* 3 ...
  22: 3*  [huh 2]

<unnamed port>:22:24: In expression (factorial (- n 1)):
<unnamed port>:22:24: Wrong type to apply: huh
ABORT: (misc-error)
guile> 

So I am somewhat fuzzy on what is supposed to work here how.

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-13 18:50     ` David Kastrup
@ 2012-01-14  1:07       ` Mark H Weaver
  2012-01-14  8:59         ` David Kastrup
  0 siblings, 1 reply; 17+ messages in thread
From: Mark H Weaver @ 2012-01-14  1:07 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

Probably the easiest way to think about it is that (the-environment)
acts like (list (lambda () <expr>) ...), with one `lambda' for each
expression that you will later pass to `local-eval'.  Calling
`local-eval' simply calls the appropriate procedure in that list.

Of course, it can't actually work that way, but that's an easy way to
think about it.  You could also imagine that it builds an infinite list,
one for each possible expression.

Calling the procedure created by a lambda expression evaluates the
lambda body within the _lexical_ environment of the lambda expression,
but within the _dynamic_ environment of the procedure call.  Top-level
variables are part of the _lexical_ environment.  That means that
top-level variable references within a procedure are looked up in the
module where the procedure was defined, _not_ the (current-module) at
the time of the procedure call.

Similarly, calling `local-eval' evaluates the expression within the
lexical environment of (the-environment), but within the _dynamic_
environment of the call to `local-eval'.

The dynamic environment conceptually includes the current continuation,
the set of fluid/parameter bindings currently in effect, and also
determines the associated dynamic extent for purposes of dynamic-wind,
catch/throw, etc.

The lexical environment includes bindings for lexical and top-level
module variables, syntactic keywords, pattern variables, etc.

David Kastrup <dak@gnu.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> David Kastrup <dak@gnu.org> writes:
>>> I am still fuzzy on what local-eval will do when the current module at
>>> the time of the-environment is different from that at the time of
>>> local-eval.
>>
>> (the-environment) saves the module (where it is textually located) in
>
> What does "where it is textually located" mean?

This simple description covers the common case where a module is defined
in its own source file with `define-module' at the top.  (I covered
other cases in subsequent sentences).  It means the module that actually
contains the string "(the-environment)".  For example, suppose you
define the following macro in module (A):

  (define-syntax-rule (foo)
    (let ((x 1) (y 2))
      (the-environment)))

and then in module (B) you evaluate:

  (let ((x 111) (y 222))
    (foo))

The captured lexical environment includes the bindings for `x' and `y'
from the macro definition of (foo), i.e. the variables that are
initially set to 1 and 2, and it also includes a reference to module
(A), because modules are conceptually part of the lexical environment.

Why?  Because if you replaced (the-environment) with (list x y z), the
reference to `z' would refer to the binding of `z' in the module where
(foo) was defined, namely module (A).  It's as simple as that.

>> I heartily disagree.  A module is conceptually part of every lexical
>> environment evaluated within that module.
>
> What does "evaluated within a module" mean?

I used sloppy wording there.  Let me try again.

Forms passed to `eval' are part of the module specified by `eval's
second parameter.

Forms passed to `primitive-eval' are part of the module returned by
(current-module) at the time when `primitive-eval' was called.

Within a compiled file, it is possible to change the module part way
through the file, using either `define-module' or something like this:

  (eval-when (compile)
    (set-current-module (resolve-module '(foo bar))))

and in this case, top-level forms after this `eval-when' are part of the
(foo bar) module.

The key point is, every top-level form belongs to a single module.  The
module is baked into the top-level form at macro expansion time, and
cannot later be changed.  It is this _fixed_ compile-time module where
top-level variable references are looked up, and therefore this is the
module captured by (the-environment).

     Mark



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14  1:07       ` Mark H Weaver
@ 2012-01-14  8:59         ` David Kastrup
  2012-01-14 15:04           ` Andy Wingo
  2012-01-14 16:17           ` Mark H Weaver
  0 siblings, 2 replies; 17+ messages in thread
From: David Kastrup @ 2012-01-14  8:59 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> Probably the easiest way to think about it is that (the-environment)
> acts like (list (lambda () <expr>) ...), with one `lambda' for each
> expression that you will later pass to `local-eval'.  Calling
> `local-eval' simply calls the appropriate procedure in that list.

Well, I experimented around a bit with lambda.  How does this work in
practice?  In Guilev1, the module is probably recorded as part of the
procedure-environment.  In Guilev2, a variable reference is compiled?
How does that work when there is no such variable?  It gets created with
an undefined binding?

> Calling the procedure created by a lambda expression evaluates the
> lambda body within the _lexical_ environment of the lambda expression,
> but within the _dynamic_ environment of the procedure call.  Top-level
> variables are part of the _lexical_ environment.  That means that
> top-level variable references within a procedure are looked up in the
> module where the procedure was defined, _not_ the (current-module) at
> the time of the procedure call.

Ok, here is the clincher and probably what I have actually confused this
with (it is a thin line): within local-eval, what is the return value of
calling (current-module)?  I would expect that it is the same as outside
of local-eval so that (define x 5) inside of local-eval would _not_ be
equivalent to (module-define! (current-module) 'x 5) as the first one
would take the current module at the-environment time, and the second
one would take it at local-eval time.

Correct?

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-14  8:59         ` David Kastrup
@ 2012-01-14 15:04           ` Andy Wingo
  2012-01-14 15:16             ` David Kastrup
  2012-01-14 16:17           ` Mark H Weaver
  1 sibling, 1 reply; 17+ messages in thread
From: Andy Wingo @ 2012-01-14 15:04 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

On Sat 14 Jan 2012 09:59, David Kastrup <dak@gnu.org> writes:

> In Guilev1, the module is probably recorded as part of the
> procedure-environment.  In Guilev2, a variable reference is compiled?
> How does that work when there is no such variable?  It gets created
> with an undefined binding?

Guile 2.0.x records the module that was current when the procedure was
created, if it is necessary to resolve toplevel bindings.

> within local-eval, what is the return value of calling
> (current-module)?  I would expect that it is the same as outside of
> local-eval

Yes.

> so that (define x 5) inside of local-eval would _not_ be equivalent to
> (module-define! (current-module) 'x 5) as the first one would take the
> current module at the-environment time, and the second one would take
> it at local-eval time.

This would be a lexical definition, and probably not allowed by the
current code.

Regards,

Andy
-- 
http://wingolog.org/



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 15:04           ` Andy Wingo
@ 2012-01-14 15:16             ` David Kastrup
  2012-01-14 15:33               ` Andy Wingo
  0 siblings, 1 reply; 17+ messages in thread
From: David Kastrup @ 2012-01-14 15:16 UTC (permalink / raw)
  To: guile-devel

Andy Wingo <wingo@pobox.com> writes:

> On Sat 14 Jan 2012 09:59, David Kastrup <dak@gnu.org> writes:
>
>> so that (define x 5) inside of local-eval would _not_ be equivalent to
>> (module-define! (current-module) 'x 5) as the first one would take the
>> current module at the-environment time, and the second one would take
>> it at local-eval time.
>
> This would be a lexical definition, and probably not allowed by the
> current code.

Two half-sentences, and each one makes me go WHAT!?!?!?!

I assume that "this" means "the second one".  Why would a module-define!
call be a lexical definition?  And why would it not be allowed by "the
current code" and what does "the current code" mean in that context?

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-12 21:43 A plea for local-eval in 2.0.4 Mark H Weaver
  2012-01-12 23:02 ` Bruce Korb
  2012-01-13  9:20 ` David Kastrup
@ 2012-01-14 15:24 ` Andy Wingo
  2 siblings, 0 replies; 17+ messages in thread
From: Andy Wingo @ 2012-01-14 15:24 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

Hi Mark,

Thanks again for working on local-eval.  I didn't like it at first, but
you did an admirable job handling all of the semantic, implementation,
and social nitty-gritties in order to solve the problem nicely.
Excellent!

If it is the case that it gets in for 2.0.4, then great.  We should try
for that.  But if for some reason it has to wait for 2.0.5, your effort
would not be wasted, not in the least!  Though of course I understand
your anxiousness to get it in.

I will look again at your latest patch and comments.  Let's continue the
discussion over there.

Andy
-- 
http://wingolog.org/



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 15:16             ` David Kastrup
@ 2012-01-14 15:33               ` Andy Wingo
  0 siblings, 0 replies; 17+ messages in thread
From: Andy Wingo @ 2012-01-14 15:33 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

On Sat 14 Jan 2012 16:16, David Kastrup <dak@gnu.org> writes:

> Andy Wingo <wingo@pobox.com> writes:
>
>> On Sat 14 Jan 2012 09:59, David Kastrup <dak@gnu.org> writes:
>>
>>> so that (define x 5) inside of local-eval would _not_ be equivalent to
>>> (module-define! (current-module) 'x 5) as the first one would take the
>>> current module at the-environment time, and the second one would take
>>> it at local-eval time.
>>
>> This would be a lexical definition, and probably not allowed by the
>> current code.
>
> Two half-sentences, and each one makes me go WHAT!?!?!?!

The drama is unnecessary, thanks.

> I assume that "this" means "the second one".  Why would a module-define!
> call be a lexical definition?  And why would it not be allowed by "the
> current code" and what does "the current code" mean in that context?

I mean that currently, with Mark's current patches, the only ones which
allow local-eval in 2.0, definitions are not allowed.  A call to
module-define! is a procedure call, not a definition.

Andy
-- 
http://wingolog.org/



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14  8:59         ` David Kastrup
  2012-01-14 15:04           ` Andy Wingo
@ 2012-01-14 16:17           ` Mark H Weaver
  2012-01-14 17:20             ` David Kastrup
  2012-01-14 17:59             ` Mark H Weaver
  1 sibling, 2 replies; 17+ messages in thread
From: Mark H Weaver @ 2012-01-14 16:17 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:
> within local-eval, what is the return value of calling
> (current-module)?  I would expect that it is the same as outside of
> local-eval

Actually, this is not true.  Within `local-eval', (current-module) is
temporarily restored (using dynamic-wind) to the module saved in the
lexical environment.

This is probably not optimal.  Among other things, it breaks the nice
equivalence <expr> == (local-eval '<expr> (the-environment)), but
`local-eval' and `local-compile' are based on `eval' and `compile', and
this is what `eval' and `compile' do (for some reason unknown to me).

> so that (define x 5) inside of local-eval

As Andy pointed out, I deliberately restrict the form passed to
`local-eval' (or `local-compile') to be an _expression_.  (define x 5)
is not an expression; it is a definition.  I explained the reason for
this restriction a few days ago[1] on this list.

> would _not_ be equivalent to (module-define! (current-module) 'x 5) as
> the first one would take the current module at the-environment time,
> and the second one would take it at local-eval time.

Actually, because `local-eval' restores (current-module) to the one
saved in the lexical environment, (module-define! (current-module) 'x 5)
within `local-eval' actually defines the variable within the saved
module, i.e. the module used for lookup if you replace (the-environment)
with a top-level variable reference.

      Mark


[1] Message to guile-devel dated 08 Jan 2012 15:39:36 -0500, with
    subject "Re: [PATCH] Implement local-eval, local-compile, and
    the-environment"



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 16:17           ` Mark H Weaver
@ 2012-01-14 17:20             ` David Kastrup
  2012-01-14 17:59             ` Mark H Weaver
  1 sibling, 0 replies; 17+ messages in thread
From: David Kastrup @ 2012-01-14 17:20 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> David Kastrup <dak@gnu.org> writes:
>> within local-eval, what is the return value of calling
>> (current-module)?  I would expect that it is the same as outside of
>> local-eval
>
> Actually, this is not true.  Within `local-eval', (current-module) is
> temporarily restored (using dynamic-wind) to the module saved in the
> lexical environment.
>
> This is probably not optimal.  Among other things, it breaks the nice
> equivalence <expr> == (local-eval '<expr> (the-environment)), but
> `local-eval' and `local-compile' are based on `eval' and `compile', and
> this is what `eval' and `compile' do (for some reason unknown to me).

This is likely going to be a problem.  One can probably fudge around it
with something like
(local-eval `(let ((current-environment (lambda ()
                     ,(current-environment))))
                  ...
but that does not look like it would really prettify things.

>> so that (define x 5) inside of local-eval
>
> As Andy pointed out, I deliberately restrict the form passed to
> `local-eval' (or `local-compile') to be an _expression_.  (define x 5)
> is not an expression; it is a definition.  I explained the reason for
> this restriction a few days ago[1] on this list.
>
>> would _not_ be equivalent to (module-define! (current-module) 'x 5) as
>> the first one would take the current module at the-environment time,
>> and the second one would take it at local-eval time.

Well, use set! amd module-set! then for the example.

> Actually, because `local-eval' restores (current-module) to the one
> saved in the lexical environment, (module-define! (current-module) 'x
> 5) within `local-eval' actually defines the variable within the saved
> module, i.e. the module used for lookup if you replace
> (the-environment) with a top-level variable reference.

Looks awkward.  And is not compatible with Guilev1 behavior:

guile> (save-module-excursion (lambda () (let ((env (the-environment))) (set-current-module (resolve-module '(none))) (local-eval '(current-module) env))))
#<directory (none) b6f7c360>
guile> 


-- 
David Kastrup



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 16:17           ` Mark H Weaver
  2012-01-14 17:20             ` David Kastrup
@ 2012-01-14 17:59             ` Mark H Weaver
  2012-01-14 18:04               ` David Kastrup
  1 sibling, 1 reply; 17+ messages in thread
From: Mark H Weaver @ 2012-01-14 17:59 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

> David Kastrup <dak@gnu.org> writes:
>> within local-eval, what is the return value of calling
>> (current-module)?  I would expect that it is the same as outside of
>> local-eval

I wrote:
> Actually, this is not true.  Within `local-eval', (current-module) is
> temporarily restored (using dynamic-wind) to the module saved in the
> lexical environment.
>
> This is probably not optimal.  [...]

Sorry, I was mistaken on this point, and most the rest of my email was
based on this false premise.

`local-eval' and `local-compile' temporarily restore (current-module)
during compilation, but _not_ during evaluation of the local expression.
Therefore, your statement above was indeed correct, and my
implementation actually does the right thing.

With this in mind, let me try again to respond this other question:

>>> so that (define x 5) inside of local-eval
>>
>> As Andy pointed out, I deliberately restrict the form passed to
>> `local-eval' (or `local-compile') to be an _expression_.  (define x 5)
>> is not an expression; it is a definition.  I explained the reason for
>> this restriction a few days ago[1] on this list.
>>
>>> would _not_ be equivalent to (module-define! (current-module) 'x 5) as
>>> the first one would take the current module at the-environment time,
>>> and the second one would take it at local-eval time.
>
> Well, use set! amd module-set! then for the example.

Indeed, (local-eval '(set! x 5) <env>) is _not_ equivalent to
(module-set! (current-module) 'x 5).

Assuming that `x' is not locally bound within the captured lexical
environment, the first sets `x' in the module captured by
(the-environment), i.e. the module where `x' would have been set if you
had put (set! x 5) in place of (the-environment).  The second sets `x'
in the (current-module) at the time of evaluation.

     Mark



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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 17:59             ` Mark H Weaver
@ 2012-01-14 18:04               ` David Kastrup
  2012-01-14 18:35                 ` David Kastrup
  2012-01-14 19:04                 ` Mark H Weaver
  0 siblings, 2 replies; 17+ messages in thread
From: David Kastrup @ 2012-01-14 18:04 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> Indeed, (local-eval '(set! x 5) <env>) is _not_ equivalent to
> (module-set! (current-module) 'x 5).

To clarify: I was thinking about

(local-eval '(set! x 5) <env>) vs
(local-eval '(module-set! (current-module) 'x 5) <env>)

> Assuming that `x' is not locally bound within the captured lexical
> environment, the first sets `x' in the module captured by
> (the-environment), i.e. the module where `x' would have been set if you
> had put (set! x 5) in place of (the-environment).  The second sets `x'
> in the (current-module) at the time of evaluation.

Yes, that would be what I would expect given the two local-eval calls
above.

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 18:04               ` David Kastrup
@ 2012-01-14 18:35                 ` David Kastrup
  2012-01-14 19:04                 ` Mark H Weaver
  1 sibling, 0 replies; 17+ messages in thread
From: David Kastrup @ 2012-01-14 18:35 UTC (permalink / raw)
  To: guile-devel

David Kastrup <dak@gnu.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> Indeed, (local-eval '(set! x 5) <env>) is _not_ equivalent to
>> (module-set! (current-module) 'x 5).
>
> To clarify: I was thinking about
>
> (local-eval '(set! x 5) <env>) vs
> (local-eval '(module-set! (current-module) 'x 5) <env>)
>
>> Assuming that `x' is not locally bound within the captured lexical
>> environment, the first sets `x' in the module captured by
>> (the-environment), i.e. the module where `x' would have been set if you
>> had put (set! x 5) in place of (the-environment).  The second sets `x'
>> in the (current-module) at the time of evaluation.
>
> Yes, that would be what I would expect given the two local-eval calls
> above.

Let me check with my "reference hack" on Guilev1:

(define (my-eval form env)
  (call-with-current-continuation
   (lambda (x)
     (env (list x form)))))

(define-macro (my-env)
  (call-with-current-continuation identity))

(display
 (save-module-excursion
  (lambda ()
    (let ((env (my-env)))
      (set-current-module (resolve-module '(none)))
      (my-eval '(current-module) env)))))

=> #<directory (none) b786d380>

Even that agrees.  Not that I would be eager to analyze why.

-- 
David Kastrup




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

* Re: A plea for local-eval in 2.0.4
  2012-01-14 18:04               ` David Kastrup
  2012-01-14 18:35                 ` David Kastrup
@ 2012-01-14 19:04                 ` Mark H Weaver
  1 sibling, 0 replies; 17+ messages in thread
From: Mark H Weaver @ 2012-01-14 19:04 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> Indeed, (local-eval '(set! x 5) <env>) is _not_ equivalent to
>> (module-set! (current-module) 'x 5).
>
> To clarify: I was thinking about
>
> (local-eval '(set! x 5) <env>) vs
> (local-eval '(module-set! (current-module) 'x 5) <env>)

Unless `module-set!' or `current-module' have been rebound within the
lexical environment <env>, the following two forms are equivalent:

  (module-set! (current-module) 'x 5)
  (local-eval '(module-set! (current-module) 'x 5) <env>)

Therefore, my analysis covers the case you were thinking about as well.

     Mark


>> Assuming that `x' is not locally bound within the captured lexical
>> environment, the first sets `x' in the module captured by
>> (the-environment), i.e. the module where `x' would have been set if you
>> had put (set! x 5) in place of (the-environment).  The second sets `x'
>> in the (current-module) at the time of evaluation.
>
> Yes, that would be what I would expect given the two local-eval calls
> above.



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

end of thread, other threads:[~2012-01-14 19:04 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-12 21:43 A plea for local-eval in 2.0.4 Mark H Weaver
2012-01-12 23:02 ` Bruce Korb
2012-01-13  9:20 ` David Kastrup
2012-01-13 16:21   ` Mark H Weaver
2012-01-13 18:50     ` David Kastrup
2012-01-14  1:07       ` Mark H Weaver
2012-01-14  8:59         ` David Kastrup
2012-01-14 15:04           ` Andy Wingo
2012-01-14 15:16             ` David Kastrup
2012-01-14 15:33               ` Andy Wingo
2012-01-14 16:17           ` Mark H Weaver
2012-01-14 17:20             ` David Kastrup
2012-01-14 17:59             ` Mark H Weaver
2012-01-14 18:04               ` David Kastrup
2012-01-14 18:35                 ` David Kastrup
2012-01-14 19:04                 ` Mark H Weaver
2012-01-14 15:24 ` Andy Wingo

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