[net.lang] Introductory teaching languages

aarons@cvaxa.UUCP (Aaron Sloman) (03/02/86)

I have just noticed the correspondence about initial teaching
languages.

In 1974 we started teaching introductory courses in programming to
students in Arts and Social Studies Schools in the University of
Sussex.

We were particularly concerned to introduce concepts and techniques
relevant to Artificial Intelligence, but had to teach people who
would not necessarily go into AI or programming later. For them it
had to be a good introduction to what computing is about and give
them a feel for what is and isn't feasible for computers to do. For
those who were to become programmers we felt it was not essential to
start with a language that they were likely to use later. The
important thing was to teach the main concepts and techniques in an
enjoyable and stimulating way, on the assumption that they could
later learn the particular languages required for their jobs.

We decided against PASCAL, FORTRAN, COBOL, C etc. as (a) they were
not general enough to include examples of AI programming, abd (b)
incremental compilers were not available, making the edit-test-debug
cycle far too slow and frustrating (and imposing too big a load on
our computers). Also languages like PASCAL were ruled out because
the type-restrictions made it impossible to define general-purpose
tools like a set manipulation package. Essentially PASCAL is too
primitive as a general purpose language. BASIC was rejected as even
more primitive though it had a better environment. LOGO was far
better, but also too restricted and in those days had a stupid
syntax which mixed up editing requirements (i.e. line numbers) with
the syntax of the language in a confusing fashion.

LISP had the required power but we felt its impoverished syntax was
totally unsuitable for beginners - it's just too unreadable for
ordinary mortals. Prolog was just coming onto the scene. We felt it
was too specialised for a general introduction, though it had many
attractive features.

So we chose POP-2, a language initially developed for Artificial
Intelligence at Edinburgh university. It has much of the power of
LISP, but the syntax looks much more like PASCAL. Over the last 9
years or so we have developed POP in various directions, including
the provision of lexically scoped variables, a pattern matcher,
indefinite precision arithmetic, etc. The current version is called
POP-11 and is part of our POPLOG system. We've produced an
introductory book on POP-11 (and more books will follow):
  POP-11: A practical language for Artificial Intelligence
   by Rosalind Barrett, Allan Ramsay, Aaron Sloman,
    published: Ellis Horwood and John Wiley, Aug 1985

(The first print-run of 3000 copies sold out in 3 months. It is
being re-printed.)

POP-11 is now used for teaching and research in a lot of UK
universities and commercial organisations, and is beginning to be
used in other countries. E.g. there are some users in USA and among
DEC customers in Germany. As a language it has the advantage that it
allows conventional programming to be taught in a nice friendly
environment, and also allows students to move towards concepts of
declarative programming, logic programming, etc.

To give a feel for the language, I'll include some examples,
conventional and non-conventional. Here are two ways of defining
factorial in POP-11 (assignments go left to right using '->')
    define factorial(n) -> result;
        1 -> result;
        until n == 0 do n * result -> result; n -1 -> n; enduntil;
    enddefine;

    define factorial(n);
        if n == 0 then 1 else n * factorial(n-1) endif
    enddefine;

Local variables are dynamically scoped by default unless declared as
lexical using 'lvars'. It should have been the other way round - but
the option of lexical scoping is a recent addition.

Here are two ways of testing whether an item is an element in a
list, the second using the built-in pattern matcher.

    define iselement(item, list);
        if list == [] then false
        else item == hd(list) or iselement(item, tl(list))
        endif
    enddefine;

    define iselement(item, list);
        list matches [ ==  ^item == ]
    enddefine;

The pattern matcher treats "==" as matching an arbitrarily long
sub-list. A more powerful use of the pattern matcher is to create a
copy of a list minus a given element (if present):
    define copy_without(item,list);
        vars lefts,rights;
        if list matches [??lefts ^item ??rights] then
                [^^lefts ^^rights]
        else list
        endif
    enddefine;

"??lefts" matches arbitrarily many elements of the list, which are then
formed into a list which is assigned to the variable 'lefts'.

Using the pattern matcher, which also matches arbitrarily nested
patterns, programs can be written quickly in a few lines which would
require several nested loops and would almost certainly be
bug-ridden at first, if written in a conventional procedural
language. E.g. given item1 and item2 and a list of lists, look for a
sub-list containing item1 followed later by item2, and return a
(possibly empty) list of the elements in between item1 and item2, or
false if the items are not found:

 define find_between(item1, item2, list_of_lists) -> result;
    unless list_of_lists matches [ == [ == ^item1 ??result ^item2 == ] ==]
    then
          false -> result
    endunless
 enddefine;

e.g. using this:

    find_between("e", "h", [[a b] [c] [d e f g h i j] [k l m]]) =>
    ** [f g]

    find_between("g", "h", [[a b] [c] [d e f g h i j] [k l m]]) =>
    ** []

    find_between("e", "k", [[a b] [c] [d e f g h i j] [k l m]]) =>
    ** <false>

'=>' prints out the result, preceded by two asterisks.

PASCAL would not have such nice syntax for lists, and would require
several nested loops, one to run along the top level of
list_of_lists checking each sub-list, one to search for item1 in a
sub-list, one to search for item2, building up the list of elements
in between. The pattern specification:
    [ == [ == ^item1 ??result ^item2 == ] ==]

displays the structure as you'd think of it. "==" means "ignore
arbitrarily many elements". "^" means "use the existing value of".
"??" means assign a list of matching elements to be the value of".

POP-11 also includes strings, arrays, hashed properties, processes,
compiler-building tools, ratios, complex numbers, and user-definable
record and vector types. So although it is nice for beginners it has
enough power for the brighter and more advanced students to learn
very advanced concepts and techniques. There is a library program
that extends the list processing to provide prolog-like facilities.

(I must declare a commercial interest. POP-11 is being marketed
commercially by Systems Designers, on behalf of Sussex University,
in the UK and elsewhere, as part of our POPLOG system, which runs on
VAXen under VMS and UNIX, SUN, HP and Apollo workstations, and
GEC-63. We hope there will also be a reduced version of POP-11 for
smaller machines by mid or late 1986. However, I am not saying
POP-11 is a good language simply because we are selling it. It's the
other way round, and I hope I have included enough factual
information to counteract any bias!)
Aaron Sloman.
    Cognitive Studies Programme, University of Sussex, Brighton, UK.
PS
Lots of our students have subsequently learnt PASCAL, C,
and other languages.
-- 
Aaron Sloman, U of Sussex, Cognitive Studies, Brighton, BN1 9QN, England
uucp:...mcvax!ukc!cvaxa!aarons  arpa/janet: aarons%svga@uk.ac.ucl.cs
                                     OR     aarons%svga@ucl-cs