Lambda the Ultimate

inactiveTopic History of APL and J
started 1/5/2001; 4:27:34 AM - last post 1/10/2001; 8:08:15 PM
Ehud Lamm - History of APL and J  blueArrow
1/5/2001; 4:27:34 AM (reads: 1399, responses: 14)
History of APL and J
While we are on the subject of APL/J. This page includes two papers about the origins of these languages. The Iverson paper is a classic, and is highly recommended. The award presentation resmark about Roger Hui tell the story of J. I haven't looked in the source for ages, but in the beginning the C code for the interpreter was amazing, with heavy use of macros the code was more APL-like than C. It was a treat, but it was very frustrating at first.

Another important paper about APL (which I don't have a link for) is Language as an intellectual tool: From Hieroglyphics to APL by D. B. McIntrye.

All very much worth a read.
Posted to "" by Ehud Lamm on 1/5/01; 4:28:59 AM

Chris Rathman - Re: History of APL and J  blueArrow
1/6/2001; 1:23:33 PM (reads: 1326, responses: 1)
Every time I start to read about APL or J, my head starts to swim. The terminology used to describe the language is so radically different than that used by any other programming. Probably because it has so many original ideas that have never quite been matched. Definitely a mathematicians dream.

In breezing through some articles, I did run across a criticism of APL from Guy Steele in his article On Growing a Language. Ok, so he's biased because he likes the open ended extensibility of Scheme but his argument is that end users can't extend the dictionary of glyphs - thus providing a discontinuity between the primitives defined by the language implementor and the functionality added by the end user.

I was kind of wondering whether J had addressed this concern. Here's the full quote from Steele:

APL was designed by one man, a smart man - and I love APL - but it had a flaw that I think has all but killed it: there was no way for a user to grow the language in a smooth way. In most languages, a user can define at least some new words to stand for other pieces of code that can then be called, in such a way that the new words look like primitives. In this way the user can build a larger language to meet his needs. But in APL, new words defined by the user do not look like language primitives at all. The name of a piece of user code is a word, but things that are built in are named by strange glyphs. To add what look like new primitives, to keep the feel of the language, takes a real hacker and a ton of work. This has stopped users from helping to grow the language. APL has grown some, but the real work has been done by just the few programmers that have the source code. If a user adds to APL, and what he added seems good to the hackers in charge of the language, they might then make it be built in, but code to use it would not look the same; the user would have to change his code to a new form, because in APL a use of what is built in does not look at all like a call to user code.

Ehud Lamm - Re: History of APL and J  blueArrow
1/7/2001; 1:58:56 AM (reads: 1329, responses: 0)
As I mentioned in another thread here (in the hope of starting a discussion), notation is a very powerful tool. (Iverson's Turing Award lecture is titled notation as a tool for thought. APL/J being based on notaton, Steele's reamrk is true. Indeed this can be seen as an orthogonality issue.

However the gains in expressiveness of the language are huge.

andrew cooke - Re: History of APL and J  blueArrow
1/7/2001; 12:28:46 PM (reads: 1317, responses: 0)
It didn't harm BASIC (which had "call" IIRC)! And many (most imperative?) languages still have a separation between "control" and procedure syntax, with only procedures extendable.

I'm not trying to be difficult - I see your point (and I feel similarly about APL, although this time round it started to make a bit more sense - I guess it's a war of attrition) - it's just that I can still remember the shock when I learnt Lisp macros and found that I could do "anything".

Ehud Lamm - Re: History of APL and J  blueArrow
1/7/2001; 1:33:57 PM (reads: 1330, responses: 1)
I am not sure I get your point re BASIC.

The APL philosophy is very different than that of most other programming languages. One point of view is to say that APL requires you to think using linear algebra (matrices etc.). You apply that language (lin alg) to various problems, using APL as an executable notation. In this sense it is not a general programming language... It dictates its own way of doing things very strongly. Much more so than most other languages.

John D. Baker - Re: History of APL and J  blueArrow
1/8/2001; 7:52:11 AM (reads: 1360, responses: 0)
I remember reading this quote years ago. I basically agree with the assertion. You could never define new glyphs in APL and yes this introduced the discontinuity Steele describes.

However, to be fair to APL, all programming languages impose a grammar on names and all languages I am familiar with forbid names that do not agree with the grammar. How else could you even define what a name is in a programming language?

Also, most languages have a limited set of glyphs that we don't always think of as names, + - / et cetera. In Java Basic, and so forth such names are few in number and we over look them -- with APL, where the glyphs number almost 200, the glyphs dominate and the discrepancy between primitive name syntax and defined names is apparent.

In some languages, that allow operator overloading, you can redefine glyphs like + but it's interesting that the consenus on overloading is that it's generally a bad idea. It converts standard symbols, willy nilly, into non-standard meanings which greatly complicate reading code in any language. APL wisely forbid this right from the start.

Ehud Lamm - Re: History of APL and J  blueArrow
1/8/2001; 8:40:24 AM (reads: 1277, responses: 0)
it's interesting that the consenus on overloading is that it's generally a bad idea.

I never felt this is the consensus. Actualy overloading ( of routine names in general, not just operators) is quite popular (Ada, C++ etc.). What people shy away from is the ability to change the precedence and associativity of operators (like you can do in Prolog). This is understandable, as this causes trouble for parsers. It is also, naturaly, bad for readability.

Randy MacDonald - Re: History of APL and J  blueArrow
1/8/2001; 2:08:33 PM (reads: 1259, responses: 0)
Some untruths: . APL was not designed by one man.

. there IS a way for a user to grow the language in a smooth way: it is called "FUNCTION DEFINITION." Only a "glyph snob" would consider A + B to be fundamentally different from A PLUS B.

. The difference in APL philosopy is not primarily due to it's linear algebraic bent. It starts with the use of adverbs/operators, which redefine verbs.

. Glyphs are ALREADY overloaded, at least for the mathematical operations, where internal data representations define the code that is actually used for the various operations.

. The language fascism not only a property of APL, but also of Perl, which until recently, was a single person's whim.

Chris Rathman - Re: History of APL and J  blueArrow
1/8/2001; 3:07:00 PM (reads: 1259, responses: 0)
Just a quick question concerning symbols and notation. I found the J Vocabulary in the J documents. For APL, the best I could find was the APL2 Symbols Table.

Is the APL table fairly representative of APL symbols? I'm aware that there may be differences across APL vendors, but most of the discrepancies seemed to be the problem of how to enter the characters from an ASCII keyboard - not the symbols themselves.

Also, is there any material that gives a comparison of the J vocabulary with the APL symbols? Thinking about putting something together myself, but if someone's already done it I don't see a need to reinvent. Ok, so I'm aware that J is quite different in it's usage. Still, I'd kind of like to see a chart that shows the similar operations (even if they are not identical in semantics).

Thanks.

Chris Rathman - Re: History of APL and J  blueArrow
1/8/2001; 9:27:53 PM (reads: 1234, responses: 0)
Ok, so I got impatient. :-)

Here'sa mild stab at mapping APL2 Symbols to J Vocabulary.

Let me know of any obvious mistakes (and if you can fill in the gaps that would also be helpful).

Thanks.

andrew cooke - Re: History of APL and J  blueArrow
1/9/2001; 12:10:38 AM (reads: 1316, responses: 0)
Sorry, the reply was to Chris's comment about a discontinuity between built-in and user-supplied procuedures (or whatever).

[I think this time I'm replying on a sub-thread (by clicking on the cow skull after a post) - let's see what happens...] [Nope. Still gets placed at the end of the page. OK, this reply was in response to Ehud saying he didn't understand my comment about BASIC...]

Chris Rathman - Re: History of APL and J  blueArrow
1/9/2001; 7:04:43 AM (reads: 1215, responses: 0)
Feeling a tad argumentative today, so I thought I'd venture into speculative land. :-)

Some untruths: . APL was not designed by one man.
I assume APL has had input from quite a few different people with a number of different vendors stretching the capability of the language (not to mention incompatible derivatives such as J, K, Nial, etc).

The point, though, that Steele is trying to make is that the control of the notation is in the hands of the few - as opposed to the masses. The types of things users do with languages is usually well beyond the visions of the original language designers. In order for a language to evolve into a general purpose language, it should be extensible to fit the needs of a multitude of niche applications.

That said, I personally like languages that reflect the vision of a single person. IMHO, C++ was a better language prior to being turned over to a standards committee.

. there IS a way for a user to grow the language in a smooth way: it is called "FUNCTION DEFINITION." Only a "glyph snob" would consider A + B to be fundamentally different from A PLUS B.
And that brings up a fundamental question about the notation used in APL and J. Do the languages derive their power from the use of shorthand glyphs and the inherent terseness provided by such?

My belief is that the notation certainly influences the readability and writeability (sometimes for the better, sometimes for the worse). But I don't think that shorthand notation is where the languages derive their power. Instead, I'd point to the higher level data structures (arrays, matrices, tables, etc) and the ability to manipulate them in a much more concise manner than any other language (at least as fluidly). I'll get to verb/adverb combinatorials below.

But if you consider glyphs to be more than syntactic sugar and a fundamental character of the languages, then it's important to consider how those symbols evolve over time.

. The difference in APL philosopy is not primarily due to it's linear algebraic bent. It starts with the use of adverbs/operators, which redefine verbs.
I do think the algebraic bent makes the language useful for a whole class of problems, but your point is well taken.

In my mind, the terminology of redefining verbs through adverbs is parallel to the Higher Order Functions in the FP languages (ML, Haskell, etc). What they seem to represent is functions that operate on other functions, similar to the idea of Map and Fold, etc...

. Glyphs are ALREADY overloaded, at least for the mathematical operations, where internal data representations define the code that is actually used for the various operations.
All languages and VM's ultimately compile down to machine language, though at that level of abstraction, things really change models. The question, though, is whether glyphs represent a higher level of abstraction. Note: an abstraction may not just be a computational item - with communication being of equal importance.

. The language fascism not only a property of APL, but also of Perl, which until recently, was a single person's whim.
I don't think Steele is accusing Iverson (or Wall) of imposing their own will on the language. The question is simply one of extensibility. If you can not extend a language, it becomes an all or nothing proposition - either it does what you need it do or it fails the requirements.

I personally believe that language designers (Steele, Iverson, Wall, Wirth, Stroustrap, etc) are quite reasonable and responsible with their caretaker positions over their respective languages. But at the top level of design, all decisions come with tradeoffs in orthoganility, expressiveness and complexity. Some designers, like Wirth, err on the side of simplicity. Other designers, like Stroustrap, err on the side of complexity.

Chris Rathman - Re: History of APL and J  blueArrow
1/9/2001; 7:15:43 AM (reads: 1219, responses: 0)
It didn't harm BASIC (which had "call" IIRC)! And many (most imperative?) languages still have a separation between "control" and procedure syntax, with only procedures extendable.
Having done way too much VB, I don't know that I'd consider BASIC to have been a language that's properly evolved over time. But I suppose BASIC (as well as Java's primitive problem) do show that such things are not crippling to a language's marketibility. And some of the most extensible languages that I've seen (Lisp, Smalltalk, etc) are not exactly the most commercially successful - but I think their extensibility has also allowed them to survive the years.

jayson_sf - first J interpreter source code  blueArrow
1/10/2001; 4:23:37 PM (reads: 1305, responses: 0)
sorry, if the line wrapping messed this up. go checkout the story and better formated code at http://www.kx.com/listbox/k/msg03690.html

The person who wrote this, Arthur Whitney, has a language that competes with J, called K. since starting to learn K about 4 months ago, I have not touched another language,

the next K version is on the horizon (check the archives for K4), and i cannot wait.

typedef char C;typedef long I; typedef struct a{I t,r,d[3],p[2];}*A; #define P printf #define R return #define V1(f) A f(w)A w; #define V2(f) A f(a,w)A a,w; #define DO(n,x) {I i=3D0,_n=3D(n);for(;i<_n;++i){x;}} I *ma(n){R(I*)malloc(n*4);}mv(d,s,n)I *d,*s;{DO(n,d[i]=3Ds[i]);} tr(r,d)I *d;{I z=3D1;DO(r,z=3Dz*d[i]);R z;} A ga(t,r,d)I *d;{A z=3D(A)ma(5+tr(r,d));z->t=3Dt,z->r=3Dr,mv(z->d,d,r); R z;} V1(iota){I n=3D*w->p;A z=3Dga(0,1,&n);DO(n,z->p[i]=3Di);R z;} V2(plus){I r=3Dw->r,*d=3Dw->d,n=3Dtr(r,d);A z=3Dga(0,r,d); DO(n,z->p[i]=3Da->p[i]+w->p[i]);R z;} V2(from){I r=3Dw->r-1,*d=3Dw->d+1,n=3Dtr(r,d); A z=3Dga(w->t,r,d);mv(z->p,w->p+(n**a->p),n);R z;} V1(box){A z=3Dga(1,0,0);*z->p=3D(I)w;R z;} V2(cat){I an=3Dtr(a->r,a->d),wn=3Dtr(w->r,w->d),n=3Dan+wn; A z=3Dga(w->t,1,&n);mv(z->p,a->p,an);mv(z->p+an,w->p,wn);R z;} V2(find)true V2(rsh){I r=3Da->r?*a->d:1,n=3Dtr(r,a->p),wn=3Dtr(w->r,w->d); A z=3Dga(w->t,r,a->p);mv(z->p,w->p,wn=3Dn>wn?wn:n); if(n-=3Dwn)mv(z->p+wn,z->p,n);R z;} V1(sha){A z=3Dga(0,1,&w->r);mv(z->p,w->d,w->r);R z;} V1(id){R w;}V1(size){A z=3Dga(0,0,0);*z->p=3Dw->r?*w->d:1;R z;} pi(i){P("%d ",i);}nl(){P("\n");} pr(w)A w;{I r=3Dw->r,*d=3Dw->d,n=3Dtr(r,d);DO(r,pi(d[i]));nl(); if(w->t)DO(n,P("< ");pr(w->p[i]))else DO(n,pi(w->p[i]));nl();}

C vt[]=3D"+{~<#,"; A(*vd[])()=3D{0,plus,from,find,0,rsh,cat}, (*vm[])()=3D{0,id,size,iota,box,sha,0}; I st[26]; qp(a){R a>=3D'a'&&a<=3D'z';}qv(a){R a<'a';} A ex(e)I *e;{I a=3D*e; if(qp(a)){if(e[1]=3D=3D'=3D')R st[a-'a']=3Dex(e+2);a=3D st[ a-'a'];} R qv(a)?(*vm[a])(ex(e+1)):e[1]?(*vd[e[1]])(a,ex(e+2)):(A)a;} noun(c){A z;if(c<'0'||c>'9')R 0;z=3Dga(0,0,0);*z->p=3Dc-'0';R z;} verb(c){I i=3D0;for(;vt[i];)if(vt[i++]=3D=3Dc)R i;R 0;} I *wd(s)C *s;{I a,n=3Dstrlen(s),*e=3Dma(n+1);C c; DO(n,e[i]=3D(a=3Dnoun(c=3Ds[i]))?a:(a=3Dverb(c))?a:c);e[n]=3D0;R e;}

main(){C s[99];while(gets(s))pr(ex(wd(s)));}

Chris Rathman - Re: History of APL and J  blueArrow
1/10/2001; 8:08:15 PM (reads: 1215, responses: 0)
I must confess that I'm not capable of understanding the interpreter code given in K - but since the code is a pretty advanced piece, it might be hard to follow in any language.

About the the only thing that pops out at me is that it looks like it has static type checking built in. I marked off the K Technical Material page a while back when I was reading the J manuals, but haven't spent the time reading thru them. The user and reference manuals are there for anyone interested in exploring the language. (Note: for some reason the link comes up on the Kdb frame. To get to the K documentation, just click on the K on the left hand frame).

Do I gather that you had experience in either APL or J before diving into K? And while we're at it, what is there specifically about the language that makes it useful from your domain?