This is the mail archive of the
guile@sources.redhat.com
mailing list for the Guile project.
Re: continuation theory (Re: Translators, yet once more)
X-From_: guile-return-4647-jmax=toad.net@sources.redhat.com Mon Jul 10 23:39:37 2000
Mailing-List: contact guile-help@sourceware.cygnus.com; run by ezmlm
Precedence: bulk
List-Unsubscribe: <mailto:guile-unsubscribe-jmax=toad.net@sources.redhat.com>
List-Subscribe: <mailto:guile-subscribe@sources.redhat.com>
List-Archive: <http://sources.redhat.com/ml/guile/>
List-Post: <mailto:guile@sources.redhat.com>
List-Help: <mailto:guile-help@sources.redhat.com>, <http://sources.redhat.com/ml/#faqs>
Sender: guile-owner@sources.redhat.com
Date: Tue, 11 Jul 2000 13:38:53 +1000
From: Telford Tendys <telford@eng.uts.edu.au>
Content-Type: text/plain; charset=us-ascii
> > Don't to it ! Continuations are REAL slow in guile and Python relies on
> > exceptions quite heavily.
>
> My understanding of this is that guile implements continuations by
> stack-copying (the C stack IIRC), which is what slows it down. My question
> is: is this really necessary? Python has a "stackless" fork (i.e. one that
> doesn't use the C stack at all) which allows for efficient continuations,
> and the claim is that this doesn't slow down the language appreciably.
> Would a "stackless" guile permit more efficient continuations? What kind
> of tradeoffs are involved?
In a nutshell:
* continuations are more ``powerful'' than exceptions in the sense of
functionality -- you can put a continuation into a global variable or
pass it out as a function's return value then you can wake up that
continuation at an arbitrary future time and when you do so the stack
must reset to the state that it held at the time the continuation was
created. At most, an exception chops frames off the current stack and
always backs out to a lower level of nesting -- much easier to implement
but not good for as many different things as continuations.
* continuations do not HAVE to be used in a way that requires stack copying
but at the time you create the continuation you do not know what the
user is intending to do with that continuation so you have no way of
figuring out how much stack you need to copy so the only reliable thing
is to copy all of it. For a python emulator, such stack copies are 100%
useless because python would never do tricky things with its exceptions,
however there is no way of explaining that to scheme.
This is an instance of the basic philosophy that constantly floats to the
surface when comparing scheme to other languages. Scheme believes in
isolating the fundamental functional components of a language and providing
these to the user to allow elegant description of an algorithm. Scheme
completely ignores how difficult these features might be to implement or
how inefficient such implementations might become -- everything that might
be an implementation issue (and thus not part of the pure language description)
is hidden away from the user and all optimisations are considered to be the
responsibility of the compiler or interpreter. The reasoning being that
eventually we will achieve compilers that can optimise beyond what a human
can do anyhow (eventually probably representing about 50 to 100 years in
my estimation of the progress of the scheme language).
Then people start to use scheme, start to like it for many small jobs
that they can write up very quickly, then they realise how slow it is when
they apply it to a really big job. The next thing that happens is they try
to write ``optimised'' scheme scripts to squeeze a bit of speed out of it.
What this represents is an attempt to cater to implementation details in
a language that is designed to avoid implementation details and the result
is generally a mess.
For example, guile supports true continuations and also its own exceptions.
>From a theoretical point of view, this is effectively forcing the schemer to
decide which type of continuation they wish to use -- one with full
capabilities or one with restrictions -- so it is putting an implementation
decision into the hands of the programmer. But scheme philosophy is that
schemers don't make any implementation decisions, they only code pure
algorithms!
Thus we get to the real problem behind guile... it isn't all things to all
people AND IT NEVER WILL BE. Perl took the trouble to focus on string
processing and document scanning -- its initial objective was to replace
sed, awk and grep with a single, more powerful tool. Later on people started
building on that base and some of the additional features have been useful,
there are still a lot of applications where perl is a bad choice, for example
numerical analysis or 3D graphics. Python has a more mathematical background
and also a strict object system -- I personally find it very irritating but
other people love it... not surprising because my interests are different from
theirs.
To be a full-blown scheme implementation, guile must support the scheme
philosophy, which is not going to suit users who want their chance to control
the low level implemention nitty gritty (i.e. who want decent performance).
To be an embedded language, guile must be small and must not impose a
burden on the application writers (its current GC system does impose quite
a burden for applications that use their own storage allocation conventions
especially when the authors of those applications don't understand GC).
It must support only minimal features in the core and must have a tiny
core distribution so that someone distributing an application can offer
a read-to-go guile library just for those users who don't already have guile.
To be a scripting language it must be quick to start up.
To be an interactive language it must have online documentation, typing
shortcuts, a debugger, and extensive backtrace facilities.
To be a high performance (speed) language it needs a white hot compiler
and for scheme that implies a compiler that can resolve all the undeclared
implementation issues that scheme programmers are told they don't have
to think about (i.e. major research project).
Guile manages to handle quite a lot of these demands but fails to focus
in on any of them. Thus, whenever you compare guile to X, you find that
guile looks pretty mediocre when your domain of comparison is the
specialisation of X.
Because guile has no focus, there is no ``right'' way to do anything in
guile because there is always the question ``when you say right, what
is this going to be right for?'' the inevitable answer is ``everything''
and the end result is ``nothing much''.
For what it is worth, my personal suggestions follow:
-- Guile should make it's primary target to be an extension language
for applications. It should NOT attempt to be a scripting language,
nor should it worry if other scheme implementations can do something
that guile cannot do.
-- Guile should not make an attempt to be particularly fast. If there is
some really intensive task that needs doing then better to code it in
C and call the C function from guile.
-- Guile MUST be modular and it must be well thought out. Part of the
problem with emacs LISP is that you rapidly get huge numbers of global
variables and functions defined. We have been dicking around with module
system concepts for years while the other languages have been collecting
bigger module libraries. Anyone who is writing for guile is going to want
to release their code as a module and they are going to want to be sure
that their work will be compatible with other people and with the core
system -- they want and need a set of rules to tell them how to build
a release of their code -- no module system, no contrib.
Take a look at the R language (search for CRAN on the internet) where they
have a large printable document (several hundred pages) devoted to
explaining how to write R extensions, how to package them for distribution,
how to use other people's packages, how to document them, etc.
This is all GPL material, guile can borrow what it needs!
-- The guile core must be small and simple and easy to understand.
-- Guile should not attempt to support a multi-threading system but it should
be thread-friendly itself so that an application which uses threads can
use guile. There is absolutely no value in an extension language that
tries to spawn its own threads all over the place -- whoever is
designing the application will make their own mind up about how many
threads they need and what they are doing with them -- presume that the
application designer is right sometimes.
-- Guile should always see itself as a library... it is the servant being
asked to do the job, not the master. This is why the main() thingy rankles
with so many people. More than that, guile attempts to take over the
signal handlers, it does its own IO in a way that make it just about
impossible for a regular C program to pass a file handle into guile or
pull one out of guile, it cannot be trusted around malloc() statements
unless you use DEFER_INTS because guile's GC system presumes it is OK
to longjmp out of an arbitrary location no matter what allocation happened
to be in progress. Taking an arbitrary application written in C and
gluing guile scripting to it should have minimal impact to the code.
Anyhow, I've had my rave for the month. If everything else is ignored then
at least please get the module system together (and set in stone) as first
priority -- nothing else is worth doing until that is complete and finished.
- Tel
--
John A. Maxwell (jmax@toad.net)
Customer: I'm using Windows 98
Tech Support: Uh-huh
Customer: My computer isn't working
Tech Support: Yes, you said that