Richard A. O'Keefe <email@example.com> wrote:
| I'm actually reading this in comp.arch. The odd thing is that this _is_
| a hardware issue, not a language issue. _Hardware_ changes (large memories,
| very fast machines, cheap raster graphic displays, laser printers, &c) have
| permitted a change in language design. You couldn't, for example, have had
| visual programming languages (languages that is where programming is done
| by connecting pictures) without cheap displays.
Actually, that's not *quite* true... ;-} ;-}
The list programming language "AMBIT/L", that I played with briefly
[and most enjoyably!] in the early 1970's, used textual Algol-like
block-structured control constructs, but predicates and data mutations
(assignments) were expressed as *pictures* which showed the interconnections
of both the "old" data and the "new" data. These pictures were printed
in character graphics in the listing file output by the compiler (sort
of the ultimate in "pretty-printing!).
You coded your program by first drawing your before & after pictures on
a pad of *paper* marked with coordinates -- basically the good old box &
pointer pictures well-loved by Lisp fans, using (well, the way I did it)
two colors of pencil for the "before" pointers/data and the "after" --
and then entered the program in a plain-text "pic"-like language that
said where the boxes were to be on the printed listing page and where
the pointer links needed to be (though *not* the routing, the compiler
would do that for you!), plus any control flow statements, etc.
A data mutation was a kind of pattern match & replace. When the control
flow reach a given pattern/block/item/(?), if the data in the global heap
matched the "before" picture, then the mutation "succeeded" and the
matching data was mutated to look like the "after" picture. If not,
the mutation "failed". As in SNOBOL (which it reminded me of a lot),
you could branch on success/failure.
Arithmetic predicates could cause success/fail, but I forget whether
it was done inside the box containing a variable or as an annotation.
(I show the latter below.) I also forget how I/O was done. Local
variable names for values could be introduced, so that data in the
"after" part could be computed from data in the "before" part.
Here's a really simple example. If you wanted to do something like:
(while (< cnt 10)
(set! cnt (+ 1 cnt))
(set! foo (car foo)))
you'd input it [I almost said "keypunch", but we had Teletypes in the
PDP-10 I ran AMBIT/L on] something like this (please pardon me for
box,2,30,15,number,tmp && tmp < 10
box,3,33,15,new_number,tmp + 1
box,6,35,20 ; (I don't recall it allowing comment, but...)
ptr,1,2 ; if "count" points to an o.k. value,
new,1,3 ; make it point to a new value.
ptr,4,5 ; if "foo" points to a list
ptr,5,6 ; or at least to a pointer cell,
new,4,6 ; move it to the pointed-to cell.
and the compiler would list it like this (really!):
| tmp | | tmp + 1 |
tmp < 10
| |---->| |
[We don't need to know anything about the data that "foo" points to
except that the first item is a pointer to another item. No local
names are needed in this case.]
My example is really too trivial to do it justice. It had the ability
to do rich pattern-matching on list structures, and you could use it
to do powerful searches of the the heap. For example, the pattern:
+---+---+ +---+---+ +------+
| | |---->| | |---->| |
+-+-+---+ +-+-+---+ +------+
| 1234 | | 5678 |
will find *any* data in the heap of the form "(1234 5678 . rest-of-list)"
and set "result" to "rest-of-list". (Hmmm... Or did searches have to be
"anchored" with at least one global variable pointing into the pattern?
I forget. But you get the idea...)
Anyway, O'Keefe is partly right in that it certainly was clumsy. As legions
of "troff" and "pic" users know, it's far more work (and one spends far
more time) to make such things pretty than to make them merely correct. ;-}
(E.g., above I deliberately made "count" and "foo" not line up -- something
one would have spent lots of time tweaking during debugging.) "Drag & drop"
would have certainly helped...
p.s. References (see a FOLDOC web server near you):
1. AMBIT -- Algebraic Manipulation by Identity Translation (also claimed:
"Acronym May Be Ignored Totally").
An early pattern-matching language, developed by C. Christensen of
Massachusetts Computer Assocs in 1964, aimed at algebraic manipulation.
2. AMBIT/L -- "An Introduction to AMBIT/L, A Diagrammatic Language for
List Processing", Carlos Christensen, Proc 2nd ACM Symp Symb and Alg
Manip (Mar 1971)].
A variant of AMBIT supporting list handling and pattern matching rules
based on two-dimensional diagrams.
Rob Warnock, 7L-551 firstname.lastname@example.org
Silicon Graphics, Inc. http://reality.sgi.com/rpw3/
2011 N. Shoreline Blvd. Phone: 415-933-1673 FAX: 415-933-0979
Mountain View, CA 94043 PP-ASEL-IA