Jot-Dot-Min
Vector 11:4, page 21
The text of this article is not yet online.
Read it in the PDF of the issue, page 21
Unedited OCR text, machine-read from the scan: it contains errors, and its APL is wrong. Shown for searching; read the PDF.
The Education Vector Vol.11 No.4
Jot-Dot-Min an outer-product of rock-bottom APL matters
Robomaniacs of the Seventies used to delight in computerising out the Man-in- the-Loop (meaning the Wiener feedback loop) as the most unreliable component. This led to a proliferation of soul-destroying jobs where the Man wasonlythere because the programmer couldn t figure out how to do without him. Many weapons systems had a man left in them solely for the purpose of having someoneto court-martial if it went off by mistake. The celebrated cybernetician Stafford Beer uttered a warning that the progress of computer systems, far from increasing wealth, would rob vast numbers of the possibility of gainful employment. Perhaps even a soul-destroyingjob is better than nojobatall.
Then the Human-Centred movementarose and turned the computing profession on its head. Far from being a weaklink in a feedback loop, a sort of liveware fuse, the human in the system (the campaign for inclusive language was underwaytoo) wasits only reason for existence. Indeed all computers were only person-to-person information pumps and a computer system nothing but a communications medium or a personal amplifier. The US Federal Communi- cations Commission (FCC) permitted Ma Bell to compete with Big Blue, thus wiping out the legally enforced distinction between data processing and electronic communication, ARPA fostered what becamethe Internet, and Apple promotedtruly interactive computers for the rest-of-us.
What happened? A generation of users grew up oblivious of job control languages, except in the twilight world of DOS batch language (the language never even got a proper name and was deliberately crippled by a lack of numerical variables or any sort of arithmetic). The soul-destroying job re- emerged, as personal computerusers struggled to earn their crust by endlessly repeating the same few menuselections and keystrokes again and again. People rediscovered the first principle of computer use: if you ever succeed in doing anything useful with a computer, you re going to wantto doit again and again, but with variations here and there, which you hope youcananticipate. Isn t that the whole of programming?
After trying to bolt-on interactive event recorders like MacroMaker in a vain attempt to record and replay useful sequences, Apple has just reinvented JCL (ob Control language) in the form of AppleScript, and appeals for all new applications to be made scriptable , i.e. programmable bya series oflines of text in a script (read: batch file) as well as executable by screen interactions.
21
The Education Vector Vol.11 No.4
Windows,the great me-too, will go the same wayin due course. Ah, butscripts can be generated by user interaction, they say. Yes, but nobody writes them that way. They re all writing programs again. And in a language that isn t even as advanced as BASIC.
In spite of Adrian Smith s article on control structures in VECTOR 11.1, which pondered the ins and outs of loops very nicely, perhaps it s time for a few musings on the subject of Branch (+). Since we're all beginners together, we won't ask whether you should be using Branchat all, but consider some of the funny things people do with it. And oneof these funny thingsis to write loops.
Fifty years of program language development(far, far longer if you go back to Babbage and Countess Lovelace) and humansarestill writing loops!It s like the Buddhist Wheel of Becoming. Santayana he say: one who forgets the past is condemnedtoreliveit.
Oneofthe joys of APL programmingis to replace loops with bit-strings, which you put together by Boolean operations.It s just like rubber-stamping a pattern instead of trying to knit it. Novices who don t grasp that, erstwhile Fortranners and Cobollers who make straight for the right-arrow and sigh ah! intelligent life! are stuck in a Santayanan loop. Here s how you write a loopif you're a C programmer: for(i=0; i<i0; i++) [ DoSomethingWith (i); }
and you write it again and again until you can write it in your sleep (and generally do). Becauseif there s one thing that C programs doto the exclusion of nearly all else, it s step through a stream of characters, filtering them. C arose out of the efforts to implement UNIX, and UNIX reduces the whole world to streams of characters which get piped throughfilters. So C is a language with a lot of plumbingin it.
It loops ten times, of course, stepping i from 0 to 9. The widget: for( ; ; ) has three slots separated by semicolons, these say whatto doat the start of the first loop, the condition for another loop, and what to doat the end of each loop.If you simply must copy this loop in APL, then APL lets you (because it's very forgiving), and the right-arrow looks comforting. Here, I ll show you the way , it seems to say. And the way is? back where you've comefrom. If you're lucky.
Here s the for-loop of C done into APL:
The Education Vector Vol.11 No.4
ied OPENBRACE:+(10<i<i+1}/CLOSEBRACE DoSomethingWith i +OPENBRACE CLOSEBRACE:
Looks uglier than it does in C, doesn t it? In both cases, the code inside the loop can be imagined to do something like: pass forward the i th characterif it s not blank. That s how youfilter out blanks the C way.
Instead of knitting the output, character by character, the APL wayis to construct a bit-string with onebit for each character in the input string(let's call it 5), a 0 bit if it s blank, a 1 bit otherwise. The 0 bits mark the characters we wanttofilter out.
Set
Putit into B like this: B+(S#' 1)
Thenthe followingis S with all the blanks squeezed out: B/S
You can putit all together in one expression: SS«(S#' ')/S
which avoidsintroducing B as a receptacleforthebit-string, using it immediately it is formed.
Yes, but how far can youstretch that principle? You can do some pretty fancy tests inside a loop, to decide whether you wantto pass forward the character or not. Surely the bit-string approach only worksfor simple things?
No. The only limit to what you can do with bit-strings is your imagination (or your commandof Boolean algebra, but you need that in C too). Suppose we wantto throw out, notjust blanks, but periods too.
B marks the blanks with zero: B« (Sz! ')
¢ marksthe periods with zero: C«(S#'.')
so BvC (read: B or C)is the bit-string we need. Or puttingit all together as before: SS«((S¥#¥' ')v(S#!'.'))/S8 In practice you'd use (~Se' .!') instead of (S#' ')v(S#'.') and you could put further characters you might wantto expel between the quotes. Butit serves toillustrate the principle. And if you'd like to throw out periods onlyif they re followed by blanks, then just shift B to the left and combine it with C:
23
The Education Vector Vol.11 No.4
(14B,1)¥¢ which flags only those periods for which there is a blank to the right of it. All together, now:
SSe( (is (Se! '),1)v(Se'.1))/5 You can doall yourfiltering this way. It would makea nice car-sticker:
APL-ers DoIt With Bit-Strings .
To quote David Diamond:
.fllas for me: My programs map to binary. No other reason need be sought Whyhalfmy work comes out to naught.
As a beginnerI usedto feel edgy about composing the whole history, in advance, of whatI expected a loop to do. Wasn'tit inefficient? Afterall, a loop only creates the truth values it needs for the current cycle. However, APL bit-strings are efficient. Very efficient. A typical C compiler will reserve a whole integer (2 bytes, or 16 bits) for a Boolean value, even in an array, but APLliterally stores bits in bits. So a 16-bit string would only occupy 2 bytes for its actual data. Of course there's the workspace overheadfor a variable, or even a transient value, but this is the same for a long bit-string as a short one. Furthermore, when you combinetwobit-strings as in BvC, the or operation isn t done a bit at a time but a word at a time. In 32-bit computers, that would combine 32 bits in a single cycle, the net result of 32 loops the C way. The more advanced the computer, the more you can expect APL to start competing with in filtering tasks. APL is about to comeinto its own with the adventof parallel computing.
Méanwhile there are occasions when you simply must have a loop. The commonest is the outer loop or duty cycle in a program which waits for user input, then acts on it. What in BASIC they usedto call the input-execute-output cycle. Instead of the C-faithful example above, you're better off using a computed branch backto the start of the cycle.
LOOP: DoSomething +LOOP IF carryon
Computed branchesare the mischief. There s a hundred and one waysthey can go wrong, and whatevery program needslike a hole in the head is a branch to
24
The Education Vector Vol.11 No.4
goodness knows where. Forthat reason alone, the right-arrow should be handled like high explosive. -
In this example, carryOnis supposed to be a scalar Boolean (a 0 or a 1), ora function (or expression) returning a scalar Boolean. Notice how we've used a dyadic function IF to make the branch more readable and provide some reassuranceit isn t going to blow up and go off on a wild branch. In I-APL you can define IF in either of two ways:
VY ZcA IF B (C1) Z+B/A v
or: IF: w/a
The use of IF is effectively the same as the commoner: +(carry0n) /LOOP because in the expression: LOOP IF carry0On a takes the value: LOOP and w takes the value: carryOn whenIFstarts to execute.
How does it work anyway? Well, 1/xxx is equivalent to xxx whatever xxx happens to be, char or num, vector or scalar. On the other hand, 0/xxx is always the empty vector. And right-arrow followed by the empty vectoris a branch to nowhere it doesjust nothing.
There s more waysof collapsing a label to the empty vector than applying / to it. You might come across: +(carry0n)+tZO0P which has much the same effect. You can also use a down-arrow to mean branchif carryOnis false , i.e. +(carry0On) +LOOP behaveslike: +(~carryOn)+LOOP.
Oneof the dreams of programmingis that whatever you write works first time. Buttake a looplikethe first example we gave. Doesit loop 9 times or 10? It could be a matteroflife or death.
I heard about a US Armyconscript who was put to work on programming. He inserted a line of code in a monthly runto print an analysis of his sergeant s parentage the day after his demob date. Unfortunately he got his < mixed up with his < and spenthis last month in uniform behind bars. The moralis: if you want something to branchreliably, always use tried andtested code.
2
The Education Vector Vol.11 No.4
Thefollowing neverlets me down: 10 repeatsOf HALLO! where:
vn repeatsof s [1] #s [2] +xnen~-1 v
but that s because I never try to write down repeat sOf from memory, but always copy it from a workspace of mypetutilities. That's the whole idea of reusable code. If it's wrong, somebody d know by now. Eat your heart out, Formal Methodology!
Speed Test: how deesthis work? Quickly now, quick-quick-quick... VLoopyLoop [1] +carry0n,DoingSomething v
That's right. The Boolean expression carry0n is supposed to return a 1 or a 0. DoingSomething must return a numeric result, or else you have to split LoopyLoopinto twolines. The catenationis a red herring, since Branch is only going to look at carry On. So we have a Brancheitherto [1](start over) or to [0] (quit). And now you know how repeat s0£ workstoo.
That'sall just aversion therapy to make you love bitmaps. But using bitmapsfor filtering really becomesinteresting at the classroom level when you apply them to 2-dimensional arrays. How do you flag the neighbours of a random assortment of elements in a 2D array? How can you use the result to build a population model where individuals infect their neighbours at random with given probability? How can you spot a Dover sole underwater? (Both the sandy bottom and the sole are random bit-arrays.) All this in the next issue, plus the rudest (uncommented) APL program ever published Conway s GameofLife as a single-liner!
Ofcourse, if anyone wants to submit solutions to these problems to the Editor, EV,in timefor the next issue, feel free! 1 shall publish acknowledgementsof the best solutions along with my own. Or instead of my own. And rememberthis Binary Data is Fun Data, butfor real laughs use a Branch!
26