Some Exercises in APL Language Design
0-origin throughout. Some of the ideas can not be implemented in a given APL because they are not backward compatible. In such cases treat them as thought experiments. There are often no right or wrong answers, or there is more than one right answer. Some of the questions were considered and decisions made years ago, but the original discussions were not recorded anywhere and I was not privy to them. Some sections do not have an explicitly stated exercise.
Treat them as ideas for meditation. Make up your own exercises.
In APL, a monadic function has the function symbol or name
preceding its argument and a dyadic function has it between its arguments.
Write each APL primitive scalar function in conventional mathematical notation.
For example,
In conventional mathematical notation,
the function symbol for multiplication is often elided:
Why doesn’t APL have an order of evaluation (operator precedence),
for example
In conventional mathematical notation
multiplication is done before addition and power is done before multiplication.
Falkoff and Iverson speculated in
If vectors
J uses terms from natural languages instead of
from mathematics or computer science
(the practice started with
The natural language terms are an extended and useful metaphor.
They are more approachable for a wider audience and more suggestive.
For example, there is usually a hiccup when explaining
The The number of arguments that a function takes is its An
The order of the arguments in many primitive dyadic functions,
when not constrained by firmly-established custom,
is such that
Why should
J has the scalar function Compare your answer to the one given below.
Compare your answer to the one given here (§4).
What is an array? Compare your answer to the one given
here.
Is a scalar an array? Compare your answer to the one given
here.
McDonnell and Shallit
1981 proposed to add to APL How can you have an infinite array in a finite computer?
One way is to consider an array as a function on the natural numbers
such that (for example) J has a few infinite arrays in disguise: Infinite vectors can be used to
prove Euler’s Identity.
In the fuss and fury of floating Devise an invertible encoding for a vector of integers as a single integer.
Such an encoding is used in the proof of Gödel’s incompleteness theorems.
A prime number is sometimes defined as a number divisible only by I have an argument supporting
In
Why is Compare your answer to
Knuth 1992,
page 6.
Let
Scalar extension can be extended in at least two different ways: In ⍝ suffix agreement x y x + y 1 2 4 0 1 2 1 3 6 8 16 32 3 4 5 11 20 37 6 7 8 7 9 12 9 10 11 17 26 43 12 13 14 13 15 18 15 16 17 23 32 49 18 19 20 19 21 24 21 22 23 29 38 55 ⍝ prefix agreement x y x × y 0 1 2 3 4 1 2 4 8 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 10 11 12 13 14 40 44 48 52 56 15 16 17 18 19 120 128 136 144 152 In its early days J had suffix agreement, but in 1992 changed
to prefix agreement and has prefix agreement to this day.
The rank operator in Dyalog APL uses scalar agreement.
The possibility remains to extend it to use suffix or prefix agreement.
The answer for
A
When dyadic
In college calculus and analysis classes we are taught that the complex numbers
can not be ordered. (The proof hinges on
that
Define an ordering on arrays, denoted here by ≼, such
that for arrays
Compare your answer to those given
here
and
here.
Can the existing function Dyalog APL can not really have a
A abcde fghij klmno pqrst $ A 4 5 (<1;4 3){A ji (<(<1);4 3){A ed on ts The first example is equivalent to (<(<'');4 3){A ed ji on ts (<a:;4 3){A ed ji on ts a: ┌┐ ││ └┘ In bracket indexing, you can elide the index for a dimension and it
would select every position in that dimension.
So the above examples are equivalent to
and more generally A[;i;;j;;k] ←→ What is the design mistake AKA missed golden opportunity?
As indicated in the previous section,
In It is instructive to read in
Early editions of
n-1 .
Is the final restriction a good idea?
x← 5 ¯2.7 0 6 (x>0)-(x<0) 1 ¯1 0 1 x × (x>0)-(x<0) 5 2.7 0 6 The expression Falkoff and Iverson explained the 0-1 definition in
Knuth wrote enthusiastically
about this (the 0-1 thing, not the array thing)
in TNN 1992,
calling it Iverson’s convention or
Iverson brackets
and
saying that it led to
“substantial improvements in exposition and technique”.
If the worked examples in TNN look familiar it’s because
the simplification steps resemble APL golfing.
In
J
defines fork, g g / \ / \ f h f h | | / \ / \ y y x y x y Why is this not equivalent to the following? (f g h) y ←→ (f y) g (h y) x (f g h) y ←→ (x f y) g (x h y)
In
Discuss the pros and cons of scalar operators
Do you still have APL2 (APL2, Dyalog APL, NARS2000, …) if you take away strand notation? “Have APL2” in the sense of, you still have APL2
if you added dfns to it.
(Or do you?)
Compare dfns (Dyalog APL)
and explicit definition (J),
two ways of defining functions and operators.
Suppose symbol proliferation is not an issue.
What are the pros and cons of
defining
In his 1978
Turing lecture
(§8) Backus wrote
“APL has exactly three functional forms, called
inner product, outer product, and reduction.”
At the time APL had two other
functional forms AKA operators. What were they?
J has
11 monadic
and 27 dyadic operators.
Which of them would you include in your APL?
Among other things, operators economize on the number of symbols needed to encode functionality. Suppose you have 10 symbols. If you use all of them to denote functions, then you have 10 functions. If you use 5 of them to denote functions and 5 to denote monadic operators, then you have 5 primitive functions and 25 derived functions. If you use 5 of them to denote functions and 5 to denote dyadic operators, then you have 5 primitive functions and 125 derived functions. These are in addition to the possibilities afforded by array operands.
The In J, the key operator In Dyalog APL, the key operator Discuss the pros and cons of each definition.
f⍢g x ←→ g⍣¯1 f g x x f⍢g y ←→ g⍣¯1 (g x) f (g y) (
The monadic case of the function The
<\ 3 1 4 1 5 9 26 NB. enclose prefixes ┌─┬───┬─────┬───────┬─────────┬───────────┬──────────────┐ │3│3 1│3 1 4│3 1 4 1│3 1 4 1 5│3 1 4 1 5 9│3 1 4 1 5 9 26│ └─┴───┴─────┴───────┴─────────┴───────────┴──────────────┘ <\. 3 1 4 1 5 9 26 NB. enclose suffixes ┌──────────────┬────────────┬──────────┬────────┬──────┬────┬──┐ │3 1 4 1 5 9 26│1 4 1 5 9 26│4 1 5 9 26│1 5 9 26│5 9 26│9 26│26│ └──────────────┴────────────┴──────────┴────────┴──────┴────┴──┘ +/\ 3 1 4 1 5 9 26 NB. sum prefix 3 4 8 9 14 23 49 +/\. 3 1 4 1 5 9 26 NB. sum suffix 49 46 45 41 40 35 26
ISO/IEC 13751:2001(E) speaks of two “reduction styles”:
Bob Smith proposed in 2016
a
combinatorial operator
for computations on combinations, permutations, partitions, etc.
Would you include it as a primitive operator in your APL?
A monadic operator is proposed for Dyalog APL in 2016,
in which a rectangular window is moved over the data and
the operand is applied to the data so framed.
The window size and the movement are independent in each dimension.
One of the things to be decided is a
Another question to be settled is a symbol for the operator.
The current proposal is
An integer array x1←2e9+?1e6⍴120 x2←2e9+?1e6⍴2e4 x4← ?1e6⍴2e9 and compare the times in takes to do Dyalog APL has 1- and 2-byte integers with automatic promotion and demotion between them and other numeric datatypes and, of course, it is immediate whether they are small-range. Having these datatypes makes a significant difference in efficiency. Define: x1←?1e6⍴120 x2←?1e6⍴2e4 x4←?1e6⍴2e9 and compare the times in takes to do The functions
Tolerant comparison ameliorates the ugly realities of
finite-precision representation and arithmetic.
For example, 7 - 100 × 0.07 ¯8.88178E¯16 7 - (7*0.5)*2 ¯8.88178E¯16 Equality with a tolerance
Compare your answers to those given
here
and
here.
assert←{⍺←'assertion failure' ⋄ 0∊⍵:⍺ ⎕signal 8 ⋄ shy←0}
The utility has counterparts in APL interpreters where it is defined as a C macro and used 700 times in Dyalog APL and 1000 times in J. Again, the main thing is that the required condition is stated in the positive sense: #define ASSERT(p,stmt) {if(!(p)){stmt;}} ASSERT(2>=r, EVRANK); ASSERT(xn==yn, EVLENGTH); ASSERT(t==APLSINT||t==APLINTG||t==APLLONG, EVDOMAIN); Absent if(!(2>=r))EVRANK; if(xn!=yn)EVLENGTH; if(!(t==APLSINT||t==APLINTG||t==APLLONG))EVDOMAIN; if(2<r)EVRANK; if(!(xn==yn))EVLENGTH; if(t!=APLSINT&&t!=APLINTG&&t!=APLLONG)EVDOMAIN;
In
In
The Imaginary/Complex section above says: J has the scalar function My answer: Complex numbers can be constructed as ordered pairs of real numbers, similar
to how integers can be constructed as ordered pairs of natural numbers
and rational numbers as ordered pairs of integers.
For complex numbers,
Written in honor and in celebration of the 50-th anniversary of APL. |