home *** CD-ROM | disk | FTP | other *** search
- From: kers@hplb.hpl.hp.com (Chris Dollin)
- Date: Tue, 17 Nov 1992 17:01:16 GMT
- Subject: An example
- Message-ID: <KERS.92Nov17170116@cdollin.hpl.hp.com>
- Organization: Hewlett-Packard Laboratories, Bristol, UK.
- Path: sparky!uunet!convex!news.utdallas.edu!wupost!usc!elroy.jpl.nasa.gov!sdd.hp.com!apollo.hp.com!cupnews0.cup.hp.com!scd.hp.com!hpscdm!hplextra!otter.hpl.hp.com!hpltoad!cdollin!kers
- Newsgroups: comp.lang.pop
- Distribution: comp
- Sender: news@hplb.hpl.hp.com (Usenet News Administrator)
- Lines: 142
- Nntp-Posting-Host: cdollin.hpl.hp.com
-
-
- Here, to whet peoples appetites, is an example of some code written in Pop11.
- It is the well-know shuffle-cards algorithm; here, it takes a list of thingies
- and delivers a new list of thingies. First, the code by itself:
-
- define shuffle( list ); lvars list, i;
- lvars vec = {% list.dl %};
- for i from vec.length by -1 to 2 do
- lvars n = i.random;
- unless n == i do (i.vec, n.vec) -> (n.vec, i.vec) endunless
- endfor;
- vec.destvector.conslist
- enddefine;
-
- And now the commentary.
-
- define shuffle( list ); lvars list, i;
-
- defines a procedure called shuffle; that is to say, a variable assigned the
- value of the procedure. Because of the context (top-level), ``shuffle'' is a
- permanent variable; it persists until it is explicitly cancelled. (Actually, it
- persists until garbage-collected, which it won't be until it is (a) cancelled,
- so there's no route to it through the symbol table, and (b) no references to it
- remain in the system.)
-
- Shuffle takes one argument, called ``list'', which is declared as a lexical
- variable (``lvar''). [The default, for historical reasons, would be as a
- dynamically local permanent variable; what Lisp would call a ``special''
- variable'']. We take the opportunity to declare another local lexical variable,
- ``i''.
-
- lvars vec = {% list.dl %};
-
- ``vec'' is another lexical, initialised to a vector (the ``{}'' brackets)
- constructed by evaluating the expression (the ``%%'' semi-brackets) ``list.dl''
- and gathering all the results up from the evaluation into the vector. The infix
- ``.'' is function application, with the function on the *right*; thus the
- function (found in) ``dl'' is applied to (the value of) ``list''. ``dl'' takes
- a list and explodes all of its elements onto the stack. (``dl'' stands for
- ``Destroy List'', although the list is not actually destroyed. ``Decompose'' is
- nearer the mark.)
-
- Hence ``vec'' becomes a vector of all the elements of ``list'', in the same
- order.
-
- for i from vec.length by -1 to 2 do
-
- A simple counting-down for-loop. Sadly the control variable is not
- automatically declared for us (roll on Pop9X). ``length'' is a general
- procedure for finding the length of suitable things, such as vectors and lists.
-
- lvars n = i.random;
-
- ``random'' is the library procedure for generating random numbers in the range
- 1 .. argument.
-
- unless n == i do (i.vec, n.vec) -> (n.vec, i.vec) endunless
-
- The only reason for the ``unless'' is to do nothing in the case where we'd
- exchange an item with itself. ``do'' could be replaced by ``then''; the two are
- equivalent. The general Pop style is to use closing keywords obtained by
- sticking ``end'' on the front of the opening keyword.
-
- ``->'' is the assignment arrow; the target(s) is(are) on the *right*. Here we
- see an assignment to a tuple, which means to assign to the components in
- right-to-left order. Because Pop is stack-based, the values to be assigned are
- waiting on the stack.
-
- I said earlier that ``.'' was postfix application, yet here it is ``vec'' that
- is being applied, and I claimed that ``vec'' was a vector. What's going on?
- Well, in Pop *any* value can be applied. For vectors, it happens that
- application means indexing; one day someone will explain how this is arranged.
-
- Even supposing that application works for vectors, what's this assignment to a
- function call? Haven't matters become even more obscure? Perhaps. In Pop,
- procedures can come equipped with *updaters*, which are themselves procedures.
- The expression ``-> F(X)'' means ``(updater(F))( X )'', ie, when a call appears
- as the target of an assignment, the updater of the procedure is what gets
- called, rather than the procedure itself. For vectors, this means that the
- updater of the underlying indexing procedure is called, giving the desired
- result.
-
- [Compare Dylan where, for obscure reasons, updaters are associated with the
- *name* of a procedure, rather than the *value* of the procedure; or Common
- Lisp, where the nearest equivalent to updaters are the setf-macros.]
-
- endfor;
-
- And here's the closing keyword for the for-statement.
-
- vec.destvector.conslist
-
- ``destvector'' explodes the elements of the vector onto the stack, and then
- pushes the length of the vector. ``conslist'' takes an argument N, and the next
- N elements off the stack, and makes them into a list, bottom-most elements at
- the front of the list. Thus we have converted a vector to a list. I might
- instead have written ``[% vec.explode %]'', similar to the initialisation
- expression for ``vec'', but I wanted to make a different point. ``[]'' are list
- brackets, just as ``{}'' are vector brackets.
-
- enddefine;
-
- And here's the closing keyowrd for the procedure definition. Trying it out:
-
- shuffle( [a b c d] ) =>
- ** [d c b a]
- shuffle( [a b c d] ) =>
- ** [c a d b]
- shuffle( [a b c d] ) =>
- ** [b a c d]
- shuffle( [a b c d e f g h i] ) =>
- ** [i b h c g e f a d]
-
- Now, this code is not particularly efficient. Most notably, it is using pretend
- calls (``i.vec'', etc) to get at vector elements; becuase there is no static
- typing [*1] the checks to see that ``vec'' has an applyable type, and to call
- the indexer, will take a fair amount of time. There are ways round this, which
- I will not address here; I'd hope to tempt Steve [*2] to do that. It also
- creates, and leaves as garbage, the vector ``vec''.
-
- Let me know if this has been an interesting exercise for the non-Pop audience.
- I'm happy to provide more snippets to illustrate the language.
-
- ----------------
-
- [*1] The nearest thing to static typing is a ``procedure'' declaration that
- arranges that procedure-valued variables can be called *quickly* (no dynamic
- check needed) at the cost of checking every assignment to the variable. There
- are also forms of constant declaration, if you think of those as being types.
-
- [*2] Steve Knight, Pop hacker and efficiency guru here at Bristol.
-
-
-
-
-
-
-
- --
-
- Regards, | I'd say that semantically C is a ramshackle hut | Meilir
- Kers. | and C++ is a two-storey ramshackle hut. | Page-Jones
-