OK, no problem. In a way, it is really simple. All data is arranged in collections (arrays) or 0 or more axes (dimensions). The number of dimensions is equal to the number of indices one needs to pinpoint a specific element.
E.g. a list (a.k.a. a vector) has a single dimension, a table (matrix) has two.
A lone element (a scalar) doesn't need any indices, so it has 0 dimensions.
And there aren't a lot of data types to keep track of. Elements can be numbers, characters, or arrays. (There are a couple of more, but you don't need to worry about them for now.)
APL takes care of internal type conversions between Booleans, Ints (of various sizes), and various floats. And also between various character widths.
So Booleans are 0/1, making computations with them straight-forward.
@david OK, enough talk. Are you ready for some exercises?
I'll give you just the functions you need, and show you how to use the APL char bot. One essential function is ⍳ (Greek Iota, for Indices or Integers):
Now, remember how APL always goes from right to left. If you want to alter the order, use parentheses exactly like you would in TMN. Now compute the sum of the first 17 squares.
APL distinguished between minus as a function and the negative sign as part of a number. For the latter, we use a high minus (like TI-Basic, btw.): ¯42
Can you compute the sum of the first 100 odd numbers?
@david APL obviously has a function to get the number of elements of an array, but can you, using just the arithmetic functions you've learned, get the length of the built-in numeric list ⎕AVU (that's just a funny four-character name, don't worry about it)?
We assign with ← which you've already seen, as ⍞ means stderr. In general, you assign to variables with var←1 2 3
⋄ is the statement separator. Normally, results from a REPL (the "session") are printed without having to be explicit about it, and you wouldn't begin statements with a statement separator, but the chat bot uses these to identify messages it should react to:
Oh, and ⎕← assigns to stdout, which for the bot means printing one or more separate lines.
Besides for the tacit functions which you got a sneak peek at, there are two other functional forms. The easiest one to master is called dfns and is indicated by putting the code in braces.
The right argument is denoted by the rightmost character of the Greek alphabet, ⍵ and the (optional) left argument is the leftmost character ⍺:
Can you write the function IsDivisibleBy? Thus ⋄ IsDivisibleBy←{your code here} ⋄ ⎕←15 IsDivisibleBy 5 ⋄ ⎕←15 IsDivisibleBy 6 should print 1 and then 0.
@david No problem. You can always ping me, and anyway, all you really need now is to build your vocabulary. When you have time, check out our chat lessons.
As I solve some practical tasks in APL using dfns, a dfn feels like a Haskell function with boolean guards and a where clause, except that a dfn also allows stateful computation and catching errors.
@Bubbler That's a good thing, right? Funny you mention that dfns havewhere clauses when John Scholes (who invented dfns) thought about addingwhere clauses.
Though, as he mentions, tracing through such a function would be a bit jarring, jumping up and down all the time. However, that's already the case for chained dfns where the order of execution is as follows:
{
3
4
}{
1
2
}
@EdgyNerd Hello and welcome to the APL Orchard. Interested in APL?
My question is, what would happen if both the main body and the where clause contains stateful computation (i.e. overwriting a variable, or "impure" code)?
@Bubbler Yes, it'd start at the leaves and work its way up. Actually, when we get the new array notation, you can create "mini-environments" to isolate "wheres":
(var:42).(var+var) won't pollute its surroundings with a var
For me it was better |x was the norm of x; and operation of division is swap, and the symbol for modulus %.... Now I rethink... All operator has to be right to left: x| has to be modulus of x, x%y is the C language y%x etc etc
If APL is a language one read right to left why division and absolute module it is right to left?
Above wrong... If APL is a language one read left to right why absolute value and division are right to left???
No it is wrong the last one
I don't know for secure, but ';' as separator seems good in the paper...one write with pencil the diamond 💎 was difficult of write
@RosLuP I agree that there are issues. In general, APL dyadic functions are designed such that the main data goes on the right and the "modifier" goes on the left. E.g. shape⍴data and amount↓data and bound|data. However, for historical reasons ÷ and - preserve their order or arguments, even though amount-⍨data and divisor÷⍨data make more sense. * is interesting, as it has two interpretations, so both * and *⍨ are meaningful. Indeed, their inverses are ⍟ and √.
One could construct a left-to-right APL where the primary data argument was on the left and the modifier was on the right, but then monadic function would probably need to be postfix, which somehow seems wrong. Maybe one could get used to a- being -x and x f is f(x)… It would let | be the current |⍨ and fit better with ÷, but on the other hand, monadic - and ÷ couldn't be seen as having 0 and 1 as "default" left argument.
Some things would look better in "LPA", like 101010₂ would be written as 1 0 1 0 1 0⊥2 and no statement separator would be necessary, as ⊢ would do the job. However, 9√2 being the square-root of 9 would be jarring, and assignments would probably need to be trailing →name (like TI-Basic, btw), which means that long rows of definitions wouldn't line up.
x! would come back to its tradition, and n!k would fit with the "nCk" name.
Even if one could accept x- as negation and x÷ as reciprocal (though a bit odd), x* and x⍟ as e*x and e⍟x would be very weird.
@EdgyNerd Me :-) I'll be very happy to give you a personalised intro right now (or at some other time), if you want. Otherwise, check out this page of learning resources.
That's ok. Thanks. Since you've done some programming, it is easy to get a crooked view of APL. To avoid that, please let go of the notion that APL is a programming language. Instead think of APL as an alternative notation to replace the Traditional Mathematical Notation (henceforth "TMN") they teach you in school.
So, for very basic things, APL is identical to TMN. It uses proper mathematical symbols instead of poor ASCII substitutes. E.g. multiplication is × and division is ÷:
Cool. This means you don't need to remember a giant order. Just remember this one simple rule: the right argument of an APL function is everything as far as it can see on its right. That's it. Period.
Don't worry if you get it wrong. Initially most do, due to being accustomed to TMN. Feel free to experiment at any time.
@EdgyNerd Yeah, in a normal APL system it means print to stderr. For the bot, it just means give me a simple inline answer.
OK, now lets talk lists (we'll get to general arrays later). APL lets you write a literal list simply by writing the elements next to each other. No need for parentheses of any sort or separators between elements. In fact, if you do use them, APL will remove them:
OK, so one of the things APL generalises from TMN is that just like - in TMN can be used with infix (between two arguments) and prefix (with an argument on its right), so can all APL functions be used in these two ways. We call them monadic and dyadic functions. E.g. The dyadic function ÷ is division and the monadic function ÷ is reciprocal (1÷x):
And it isn't really confusing as there can only ever be one or two arguments. To see which form is being used, look to the immediate left. If there's data there, it is dyadic. If there's nothing, or a function, it is monadic.
@EdgyNerd Monadic + is actually the complex conjugate, if you're into complex numbers…
APL only has two basic types, btw, numbers and characters. Super simple. That's why True is 1. Also 1 is the only True — none of this confusing truthiness business.
This is because the sum and the product are actually instances of a single concept, namely that of changing a list into a single element by inserting a dyadic function into all gaps:
So APL generalises this with something we call an operator. An operator is like a "super function" that returns a new function based on one or two parameters (depends on the operator in question) we call operands.
/ is what we call a monadic operator because it takes a single operand (on its left) and derives a new function that didn't exist before. If the operand is + we call the derived function "sum", but really any dyadic function could be used.
@EdgyNerd The correct term for +/ is "derived function". We can even give this new function a name:
⎕ and ⍞ are actually stylised icons for the console with the inner ' symbolising strings/messages, hence stderr. If you try to fetch the value of ⍞ it means stdin (but for obvious reasons, that won't work with the bot).
OK, now let me show you a really useful function, and then it is exercise time!
The Greek letter ⍳ (Iota) corresponds to our English letter I which stands for Indices or Integers. Given a single number as arguments, it generates a list of that many integer indices: