[Top][All Lists]

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

Re: Emacs Lisp and Guile

From: Marius Vollmer
Subject: Re: Emacs Lisp and Guile
Date: 01 Aug 2002 21:39:29 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1

Richard Stallman <address@hidden> writes:

>     > Scheme variables are normally lexical.  What do people normally do in
>     > Scheme when you want a dynamically scoped value?
>     In plain Scheme, you use 'dynamic-wind' to establish a dynamic
>     context.  Entering and leaving that context will run specified
>     procedures that can swap values in and out of variables that should
>     have dynamically scoped values.
> It is very undesirable for Lisp dynamic variables to be different
> from Scheme dynamic variables.  It makes the system specs incoherent.

There really aren't dynamic Scheme variables (in the sense that there
are dynamic 'special' variables in Common Lisp).  The effect where a
variable takes on a certain value during an dynamic extent and
reverting to its previous value when the context is left is not
implemented with a special kind of variable, but with a special
control flow construct that allows you to run hooks when a certain
dynamic context is entered or left.  These hooks can be used to swap
the values of a variable.

You normally hide these things behind some functions.  'dynamic-wind'
is the fundament upon which these functions are built, but it is too
clumsy to explicitly use it for dynamically scoped values.  For
example, there is no visible variable that holds the 'current output
port' (the Scheme analogon of C's stdout), but there is a function
'current-output-port' that returns the current output port, and there
is a function 'with-output-to-port' that established a new dynamic
context in which 'current-output-port' returns the specified port.
For example

    (with-output-to-port (current-error-port)
      (lambda ()
        (display "Hi\n")))

will output "Hi\n" on the current error port by temporarily switching
the current output port to the error port.

I don't think this has to be inconsistent with Lisp.

What is a typical part of the system specification that makes use of
Elisp's dynamic scoping?

Maybe I understand you wrong.  If you are saying that we should
implement Elisp's variables the way Scheme normally mimics dynamic
scoping, as opposed to saying that we should add dynamic scoping to
Scheme in order to handle the existing Emacs spec, then we have no
problem.  We already have '@bind' which can be used to implement Elisp
'let' and argument binding for function calls.  It will use
'dynamic-wind' as outlined above.

> Is it possible to extend dynamic-wind so that it can handle
> buffer-local, frame-local, etc. contexts?

No, dynamic-wind is only for control flow.  Think of it like an
extended unwind-protect (where the extension is only useful in the
presence of captured continuations).  However, we could have something
like it for buffer-local contexts, say 'buffer-wind'.  That is, we
could have a way to specify hooks that are run whenever the value of
(current-buffer) changes.  The hooks would then install the right
values in the variables that are supposed to behave buffer-locally.

I'm afraid this might turn out to be expensive and it is not a good
solution in a multi-threaded system.  I don't know whether you
consider making Emacs multi-threaded, but we should keep that option.
With something like 'buffer-wind', the values would be swapped at
every thread switch.  It wouldn't work at all for true concurrent
threads.  (We are far away from true concurrent thread support in
Guile, but we have nice cooperative threading.)

What about exporting all Elisp variables to Scheme as settable
functions?  For example

    (set! (require-final-newline) 'ask)

This would lead to a divergence between Scheme variables and Lisp
variables, but I don't think this is bad.

>     In Guile, we also have 'fluids'.  A fluid is a normal object like a
>     cons pair that holds one object per thread.  That is, fluids are our
>     mechanism for thread local variables.
> Could this be unified with dynamic-wind also?

It complements dynamic-wind and works together with it.  Fluids
provide thread-local storage and dynamic-wind is used to swap values
in and out of these locations to establish dynamic contexts.  Fluids
don't incur an overhead on every thread switch, but on every access.
They are meant to be used to implement things like
'current-output-port' in a thread-safe manner.  For example,
'current-buffer' could be implemented with a fluid.

reply via email to

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