[comp.lang.apl] recently I beheld a vision

dmlaur@phoenix.Princeton.EDU (David M. Laur) (02/28/91)

Bob recounts the Evils of Brackets:

In article <1991Feb26.210503.2798@yrloc.ipsa.reuter.COM> rbe@yrloc.ipsa.reuter.COM (Robert Bernecky) writes:
>
>I won't try to deal with all your concerns about J vs apl, but
>a. brackets are syntactically anomalous, and are not functions, operators,
>   or anything else that is generally applicable to apl.
>
>b. brackets have special and unique meanings for EACH primitive. 
>   You can't tell someone: foo[k] means thus and such. 


This reminded me of a sleepless night I spent a while back ...
in an ethnic food and beverage blur, my conciousness became
a confluence of APL, C++, Objective-C, Eiffel, and Gyoto munks.

The upshot of which was the following Zen solution to the brackets
problem: just declaring their odd behavior to be the shadow
of a misunderstood feature.

Namely: define brackets to be notation for passing unparsed messages
to objects;  then we simply say that traditional APL objects had
some (useful but inconsistant) default behavior:

  - array objects passed the messages through the execute primitive
    and treated the result of each expression (separated by ;)
    as selection indicies.

  - function objects treated the results as axis specification

but this facility was sadly misunderstood and underused!

For example, with a few msg composition functions you might add
some structured programming constructs to APL, I also believe
you get very general indirection constructs if you add one new
data type (msg).

  I'll define brackets to simply mean "the text within is ignored
     and simply passed as a message to the object on the left"

  let's use down-shoe (shift-c) to mean "collect" or "enCase"
        it simply instantiates the msg on its right as an array,
        of type 'msg', and passes it left.
        (I'll use 'n' for this symbol temporarily)
  let's use up-shoe (shift-v) as its inverse "eValuate" or "verify"
        it simply executes the text of msg objects, one expression at
        a time, expressions may be separated by semi-colons or newlines.
        (shown as 'u' below)

  we get branchless conditional execution:
    u (A=B) / n [expression]

  that is: if A equals B, evaluate the expression

  note that you get to write 'expression' normally, no
  doubling of quotes, etc.

  we get a branchless if-else construct with:
    u (A=B,C) / n [expr0] n [expr1]

  multiple expressions are separated by ';'

     u (A=B) / n [e ; f ; g] n [h]

  *or* newlines:

     u (A=B,C,D) / n [
        e
        f
        g
     ] n [
        h
        i
        j
     ] n [
        k
     ]

It's an open question as to whether the expression in brackets
would be syntax-checked and tokenized or left completely "unread"
until evaluation time.

I also believe the "encasing" operation should be allowed on
any object, yielding indirection:

    if 'F' is a function, then

       P <- n F

    gives you a "pointer" to the function 'F', and

       u P       evaluates P (calling F)

    A <- n F n G n H        (an array of function pointers)

    u A[i]                  (call function i, niladic)

    (u A[i]) 3              (monadic arg = 3)


There are, of course, nearly a million variations on this
theme (I've counted).  The point is, you might be able
to salvage some real respectability out of brackets by
declaring them to provide some modern (missing) functionality
in APL ... we just claim that indexing is a degenerate case.

So there.

[][][][][][][]

David Laur                           dmlaur@gauguin.princeton.edu
Princeton University                 dmlaur@pucc.bitnet
Interactive Computer Graphics Lab

"Talking about music is like dancing about architecture"
          - Laurie Anderson