[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon Apr 12 13:06:34 2000 
Subject:The Open Stack 
From:steve 
Volume-ID:1000412.01 

William "Billy" Tanksley writes:-
>BTW, there's a really good set of articles on open-stack languages at
><URL http://www.latrobe.edu.au/www/philosophy/phimvt/j00syn.html>.  Not
>applicable to all of Poplog, but certainly useful to anyone wishing to
>understand why open-stack usage can sometimes be useful.

First, thanks to Billy for this fascinating reference about Joy.  It was
well worth reading.

I thought it would be worth following up this with a description of the
way Chris Dollin and I handled the "open stack" idioms in a closed stack
language.  Chris and I, with help from several other people, designed
a programming language, codenamed Spice, and published its specification
on the Internet a couple of years ago.  This project continues today.

The most relevant aspect of Spice to the Poplog community is that it
finds a interesting and good compromise between the closed and open
stack.  In the remainder of this letter, I outline that compromise.

I should acknowledge that the approach taken by Spice is pretty much
the same as multiple-value returns in languages such as Scheme.  However,
because we designed Spice with this feature in mind, the overall result
is clearer.

                        ---oooOOOooo---

MULTIPLE VALUES IN SPICE

Spice functions are allowed to take an arbitrary number of
input arguments and deliver an arbitrary number of results.  To
do this, Spice allows an input parameter to be followed by "..." to
indicate that it binds to the remaining arguments.  Here's how one
writes a function -foo- that takes 2 or more arguments.

     //  The syntax is too verbose, we know.  However, this is the
     //  form most appropriate for Pop11 readers.
     define function foo( a, b, x... ) =>
         <BODY>
     enddefine

The key question, of course, is where -foo- gets its arguments from when
it is invoked.  So in the below text, which of the arguments can -foo-
get at?

     1, 2, 3, foo( 4, 5, 6 )

The answer is that, in Spice, -foo- binds its parameters to 4, 5 & 6 and
the other values 1, 2 & 3 are invisible to it.  It must bind _all_ its
parameters: neither having too few or too many arguments is acceptable.
Naturally, in the case of -foo- it cannot be given too many arguments because
the "x..." parameter can bind to a unlimited number of values.

It is this decision that makes Spice a non-open stack language.  A function
cannot dig into the stack below the arguments explicitly supplied.  However,
as we will see, it differs from closed stack languages because the
stack space required during a function call is unbounded.  For that
reason, I think of Spice as a "semi-open" stack language.

There are two mechanisms by which more than one result can be returned,
the comma operator and loops.  The results of (E1,E2) are the results
of E1 and E2 together.  So the expression ("alpha", "beta") returns the
two strings "alpha" and "beta" in that order.

We were keenly aware of that, for our intended consituency of users,
this semi-open stack could become a problem.  So when we designed loops,
we wanted the default behaviour to dispose of unintended results.
If you wanted the loop to return a value each time round, as a open
stack language would do, you needed to say so explicitly.  We did
this by distinguishing "do" from "do all" loops.

     for i in L do i endfor        // returns no results
     for i in L do all i endfor    // effectively explodes L

We took a similar line on the ";" operator.  It disposes of the results
of the left hand side.  Thus,

     1; 2                          // returns 2
     1, 2                          // returns 1 and 2

And in the case of ":=" assignment, we insist that there are no results
left over.

     f( x ) := g( y )              // guarantees no results

Initially we were concerned with the cost associated with the semi-open
stack.  However, by annotating a function with its input and
output arity (c.f. Lisp compilers) it is trivial to do a basic arity
analysis.  It transpires that this elementary analysis is much more
effective and practical than one has any right to hope for!  So the
cost is mostly negligible.  Only the "..." arguments present any
challenge.

[If you are familiar with the Pop11 compilation model, you might protest
that this kind of analysis is only viable if you are working with
variables declared to be "constant" rather than "vars".  This is true
and we designed the Spice compilation model appropriately.  It is
straightforward for a Spice IDE to automatically record package
dependencies and recompile (or mark as dirty) when assumptions are
changed.]

The end result is a very effective compromise.  Stack errors
such as those that occasionally bedevil the Pop11 programmer are
largely eliminated - and usually spotted by the arity analysis.
The compiler-writers are happy because they can make good use of registers.
And the open-stack hackers get much of what they want.  Here's a typical
open-stack idiom repeated in Spice

     // Spice lists do NOT quasi-quote their contents.
     define function filterList( L, p ) =>
         [ for i in L do all if p( i ) then i endif endfor ]
     enddefine

Or here's how we write the equivalent to -applist- and -maplist- :-

     define function appList( L, p ) =>
         for i in L do all p( i ) endfor
     enddefine

     define function mapList( L, p ) =>
         [ applist( L, p ) ]
     enddefine

In practice, it is a fairly enjoyable compromise.  Some algorithms are
definitely a bit trickier to write than in Pop11.  But the benefits of
the arity analysis are immediate and very welcome.  I implemented this
semi-open stack in my "OWL" language, a kind of super-powered embedded
XML, and found it very pleasant for a real and sizeable web-application.

Obviously this is a bit off topic for many readers.  However, I hope it
was of interest to enough people to justify posting to this group.

Steve