This is the mail archive of the guile@sources.redhat.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

continuation theory (Re: Translators, yet once more)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]