APL Trivia: Life, the Universe and Everything?; Remarks on “Towards a Better APL”
Vector 2:4, page 115
Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 115
Doubtful transcription
Henriod’s APL listings (printed pp.117–119) are a rough dot-matrix print in which several glyphs are doubtful; check them against the page before relying on the code. The prose is reliable.
Life, the Universe and Everything?¶
In VECTOR Vol 2, No.2, we looked at a function that applied all the monadic primitives to 0 to produce the answer to the ultimate question, as “Hitch-hiker” fans will recall. A challenge was set to find the largest possible number obtained by scrambling the order of the primitives. Claude Henriod from Switzerland produced this interesting piece of code:
∇ R←BIGANSWER1
[1] R←⍎⌽⍕-⍟!|+⌹○÷*⌈⌊×⍉⊖~⍴⍒⍋,?⍳0
∇
BIGANSWER1
1.836014905E10
⎕PP←17
BIGANSWER1
6.53239608360149E17
⎕PP←10
Can you see why the result gets larger as the value of the system variable ⎕PP is increased? Mark Bassett supplied the following code to produce the biggest answer he could find:
Can anyone improve on this, or perhaps prove that it can or cannot be bettered?
It seems that “Ivor Kenson’s” article “Steps Toward a Better APL” caused a bit of confusion, and was taken seriously by at least two people! (Now doesn’t that name seem somehow familiar?). Claude Henriod was so incensed that he has not only produced a criticism of the original article, but also sent us with his own version of what a simulation of BASIC in APL should look like. Let’s have a look at what Claude has to say, with thanks to Helen Piper for providing the translation, but after this, please – no more BASIC emulators!
Remarks on “Towards a Better APL”¶
by Claude Henriod
In general one has the impression that the author of these APL functions is a FORTRAN programmer.
The APL listings which accompany these notes have been developed and tested with APL-68000 V5.0 on an Ampere computer.
1. Some simple improvements:¶
- ELSE, RETURN, STOP are unchanged.
- GOTO, IF are simplified.
- BASICDEMO and my equivalent FIBOBASIC are no comparison with the APL function FIBO.
- THEN uses 4 lines and 2 branches and is too complicated in APL.
- NEXT is so much simpler in APL.
- STEP is a BASIC keyword which must be included.
- ON is associated with GOTO, for example:
GOTO (L100,L200,L300) ON INDEX
2. Comments on Mr. Kenson’s code¶
- Allowing assignment to ⎕WA is a weakness in some interpreters. It is always dangerous to use the errors of a system, since a new version could correct them.
- APL-68000 does not allow assignment into ⎕WA, and also does not understand ⎕ALX or ⎕ELX, and so I think it is preferable to use local variables with a naming standard.
- FOR and INPUT contain the same sequence of code which can be extracted as a sub-function (see also READ).
- Line 3 is simplified
- Lines 2 and 4-6 are moved to SUBEXTRACT
- INPUT is closer to BASIC if a prompt is incorporated. It would also be necessary to initialise the variable or variables, as with READ.
- PRINT is a very inadequate copy of the BASIC command. It is very simple to simulate it in 3 lines (see the code in FIBOBASIC).
3. BASIC extensions¶
- FOR does not correspond to the BASIC version:
- lacks the ability to use a decreasing sequence
- cannot be nested
- the FOR....NEXT loop is executed at least once (DO-UNTIL instead of DO-WHILE).
I have not been able to resist the pleasure of completing M. Kenson’s study:
- READ, DATA and RESTORE are new functions
- READ uses SUBEXTRACT. Constraint: The variable must be initialised with the maximum length of the data, which can likened to a DIM statement.
- DATA requires an argument of a single data type, but this is not a great handicap thanks to RESTORE.
- RESTORE n. If n=0, the first line of DATA is restored. If n is not a line of DATA, RESTORE has no effect on the sequence of data.
APL-68000 has certain differences which I have used, for example Nomadic functions, but it could be written without the use of such extensions.
⎕SI is “vectorised”, so I have used ⎕BOX. ⎕SS directly gives the index of the argument being sought.
I have not copyrighted, nor do I make any reservations on the presented code, because I am only concerned with the promotion of APL.
∇ DATA ∆s∆
[1] →(2=⎕NC'DATA∆CTRL')/⎕LC+1 ⋄ DATA∆CTRL←⍳0
[2] ∆s∆←¯1↑2↑⎕LC ⋄ →(∆s∆∊DATA∆CTRL)/0
[3] DATA∆CTRL←DATA∆CTRL,∆s∆
∇
∇ R←X ELSE Y
[1] R←X,Y
∇
∇ X←FIBO N
[1] ⍝ FIBONACCI SERIE
[2] X←1 1
[3] →(N>⍴X←X,+/¯2↑X)/⎕LC
∇
∇ FIBO∆BASIC
[1] ⍝ REM SIMULATED BASIC PROGRAMM IN APL
[2] N←0
[3] 'GIVE FIBO LIMIT'INPUT N
[4] L100:→IF(N≤0)THEN STOP ELSE L200
[5] L200:I←1
[6] R←0
[7] S←1
[8] L300:→IF(I=N)THEN GOTO L400
[9] →GOSUB L500
[10] PRINT I,R
[11] I←I+1
[12] →GOTO L300
[13] L400:→GOSUB L500
[14] PRINT I,R
[15] X←''
[16] FOR I←1 TO R
[17] PRINT'*;'
[18] →NEXT I
[19] PRINT'*'
[20] →STOP
[21] L500:T←S
[22] S←R+S
[23] R←T
[24] →RETURN
∇
∇ FOR FOR;∆a∆;∆e∆;∆i∆;∆l∆;∆s∆
[1] ∆a∆←⍕1+¯1↑2↑⎕LC
[2] ∆l∆←SUB∆EXTRACT'FOR'
[3] ∆e∆←¯1↓(∆i∆←∆l∆⍳'←')↑∆l∆
[4] ⍎'∆i∆←',(∆i∆)↓∆l∆
[5] ⍎∆e∆, ←1↑∆i∆'
[6] ∆l∆←⍕¯1↑2↑∆i∆
[7] ∆s∆←⍕¯1↑3↑∆i∆,1
[8] FOR←'NEXT←(',∆l∆,'≥',∆e∆,'←',∆e∆,'+',∆s∆,')/',⍕∆a∆
[9] 0 0⍴⎕FX((⍴FOR)↑'NEXT←NEXT NEXT'),[⎕IO-0.5]FOR
∇
∇ R←GOSUB R;∆i∆;∆x∆
[1] ∆i∆←⍕1+¯1↑2↑⎕LC
[2] ∆x∆←(8⌈⍴∆x∆)↑∆x∆←'R←',∆i∆
[3] 0 0⍴⎕FX((⍴∆x∆)↑'R←RETURN'),[⎕IO-0.5]∆x∆
∇
∇ R←GOTO R
∇
∇ R←IF R
∇
∇ ∆t∆ INPUT INPUT;∆l∆;∆e∆
[1] ∆l∆←⍴,INPUT ⋄ ∆e∆←0≠0\0⍴INPUT ⋄ INPUT←SUB∆EXTRACT'INPUT'
[2] →(2≠⎕NC'∆t∆')/⎕LC+1 ⋄ PRINT ∆t∆
[3] →∆e∆/⎕LC+1 ⋄ ∆e∆←⎕ ⋄ →⎕LC+2
[4] ∆t∆←(¯1+⍴∆t∆)×';'=¯1↑∆t∆←,∆t∆ ⋄ ∆e∆←∆t∆↓⍞
[5] ∆e∆←(∆l∆⌊⍴,∆e∆)↑∆e∆
[6] →(0≠0\0⍴∆e∆)/⎕LC+1 ⋄ ⍎INPUT,'←',⍕∆e∆ ⋄ →0
[7] ⍎INPUT,'←''',∆e∆,''''
∇
∇ NEXT←NEXT NEXT
[1] NEXT←(89≥I←I+1)/16
∇
∇ R←L ON I
[1] →(=/I)0,⍴L←,L)/⍴R←⍳0
[2] R←L[⎕IO-1-I]
∇
∇ PRINT ∆x∆
[1] →(0≠0\0⍴∆x∆)/⎕LC+1 ⋄ ∆x∆ ⋄ →0
[2] →(';'=¯1↑∆x∆)/⎕LC+1 ⋄ ∆x∆ ⋄ →0
[3] ⍞←¯1↓∆x∆
∇
∇ READ READ;∆c∆;∆e∆;∆l∆
[1] ∆l∆←⍴,READ ⋄ READ←SUB∆EXTRACT'READ'
[2] →(2≠⎕NC'DATA∆LIST')/⎕LC+1 ⋄ →(0=⍴DATA∆LIST)/⎕LC+1 ⋄ →∆i∆
[3] DATA∆LIST←(1↑DATA∆CTRL)SUB∆EXTRACT'DATA' ⋄ DATA∆CTRL←1⌽DATA∆CTRL
[4] ∆i∆:∆c∆←-⎕IO-DATA∆LIST⍳',' ⋄ ∆e∆←⍎∆c∆↑DATA∆LIST
[5] DATA∆LIST←(1+∆c∆)↓DATA∆LIST ⋄ ∆e∆←(∆l∆⌊⍴,∆e∆)↑∆e∆
[6] →(0≠0\0⍴∆e∆)/⎕LC+1 ⋄ ⍎READ,'←',⍕∆e∆ ⋄ →0
[7] ⍎READ,'←''',∆e∆,''''
∇
∇ READ∆BASIC
[1] DATA 1,3,5,7,11,13,17,19,23,29
[2] DATA 10
[3] DATA'BRITAIN','FRANCE','GERMANY','SWITZERLAND','ITALY'
[4] RESTORE 3
[5] FOR NO←1 TO 4
[6] TXT←8⍴' '
[7] READ TXT
[8] PRINT NO
[9] PRINT TXT
[10] →NEXT NO
[11] RESTORE 2
[12] CNT←0
[13] READ CNT
[14] RESTORE 0
[15] FOR NO←1 TO CNT STEP 2
[16] VALUE←0
[17] READ VALUE
[18] PRINT VALUE
[19] →NEXT NO
[20] →STOP
∇
∇ RESTORE ∆x∆
[1] →(0≠∆x∆)/⎕LC+1 ⋄ ∆x∆←⌊/DATA∆CTRL
[2] DATA∆CTRL←(-⎕IO-DATA∆CTRL⍳∆x∆)⌽DATA∆CTRL
[3] 0 0⍴⎕EX'DATA∆LIST'
∇
∇ R←RETURN
[1] R←13
∇
∇ R←X STEP Y
[1] R←X,Y
∇
∇ R←STOP
[1] R←0
∇
∇ ∆r∆←∆l∆ SUB∆EXTRACT ∆n∆;⎕IO
[1] →(2=⎕NC'∆l∆')/⎕LC+1 ⋄ ∆l∆←¯1↑3↑⎕LC
[2] ∆r∆←(⎕R ⎕BOX ⎕SI)[2+⎕IO←1;]
[3] ∆r∆←⎕CR ¯1↓(∆r∆⍳'[')↑∆r∆
[4] ∆r∆←,∆r∆[1+∆l∆;]
[5] ∆r∆←((¯1+⍴∆n∆)+1↑⎕SS(∆r∆;∆n∆))↓∆r∆
∇
∇ R←C THEN L
[1] R←(C,(~C)×2=⍴L)/L
∇
∇ R←X TO Y
[1] R←X,Y
∇