11 ms·
As cool as this is, APL has improved a lot in the 34 years since that video was made. Most notably, these days, APL has `direct functions`, which enable a degr
by codesections 7y ago
As cool as this is, APL has improved a lot in the 34 years since that video was made. Most notably, these days, APL has `direct functions`, which enable a degree of concision and tacit-programming support unmatched in any other programming language (yes, including Haskell).
As a minor taste of the power of direct fns, here's a naive implementation of the Fibonacci sequence with one: `fib←{1≥⍵:⍵⋄(∇⍵-1)+∇⍵-2}`
- jodrellblank 7y agoTrying to pick up some APL over the last year, I've found it mildly annoying to find APL code without explanation. I'm expecting that's fine for experienced users, even trying to work it out is useful, but it's hard to get to a point of being able to do that without some hints. This fib code in the parent comment translates to: def fib(n): if (1 >= n): return n else: return fib(n-1) + fib(n - 2) and it does so with: fib ← { "scriptblock" function declaration implicit variable name ⍵ (omega) for the right side argument 1≥⍵ : ⍵ guard case, if 1>=⍵, return ⍵ ⋄ statement separator, like ; in C-languages if no guard clauses matched, remaining code runs ∇ recursive call to the function it appears in ∇(⍵-1)+∇⍵-2 fib (⍵-1) + fib (⍵-2) } More notably, the kind of tacit programming support looks like this: (××∘⌊|+1≤2||) N Rounding to nearest even number (favouring away from 0) which evaluates to a function that takes N on the right, and the tacit train looks like this, from TryAPL.org visualization: ┌─┼────┐ × ∘ ┌─┼───┐ ┌┴┐ | + ┌─┼───┐ × ⌊ 1 ≤ ┌─┼─┐ 2 | | <- N goes in here The tree evaluates from the lower right. Each triple is a fork, N goes into the right prong, the left prong, then the result of both of those goes into the center prong. Unless there's a constant on the left prong, then that's used as-is. So: |N for the magnitude; 2|(that) for the remainder of dividing by 2; 1<=(that) to find whether to add 0 or 1 for the rounding, (|N)+(that) to re-do the magnitude of N and add the 0 or 1. xN to get the direction +1 or -1, multiplied by the floor of the calculated result. N enters in several places, which avoids having to store temporary variables and name them, when you aren't actually interested in new variables. And this works on a single number, a vector or multi-dimensional matrix of numbers.
- kazinator 7y agoThat's an example of what I call "stupid terse". When comparing program length, we should count tokens, not characters. We should give a penalty to excessively long tokens, of course, like pointlessly_long_variable_or_function_names. Say, any token longer than 8 characters counts as two tokens. Any longer than 16 counts as 4 and so on, exponentially. Pairing tokens like { } and ( ) can count as one for the pair. In syntax like f(x, y), the () are essentialy one operator denoting function application, spread out to enclose the arguments. Your APL fib←{1≥⍵:⍵⋄(∇⍵-1)+∇⍵-2} has 19 tokens. jodrelllblank's Python: def fib(n): if (1 >= n): return n else: return fib(n-1) + fib(n - 2) has 27. There is a bit of verbiage with the colons, the else punctuation and the explicit return commands. TXR Lisp: (defun fib (n) (if (plusp n) n (fib (+ (pred n) (ppred n))))) has 21 tokens (or, if you will, nodes in the syntax tree). Only two more over APL, and provides a clear function definition from which we know it takes exactly one required argument, which is given a name. It exhibits no ambiguities.
- robocat 7y ago> When comparing program length, we should count tokens, not characters. GP said APL had "concision" and you then replied about measuring tokens, ended up using some personal ƒ(tokens,nodes,symbols) for reasons I can't fathom. > It exhibits no ambiguities What ambiguities are present in the APL function? If you answer, please write clearly, because I know nothing about APL (I was watching the video for my own didactic purposes). > That's an example of what I call "stupid terse". That seems needlessly provocative to me. Edits: clarity. I think I would like the function definition to be written a little more clearly, but I would need more interaction with APL authors to understand their communication norms for their language.
- kazinator 7y ago> What ambiguities are present in the APL function? For instance: ∇⍵-2 is that ∇(⍵-2) or (∇⍵)-2? If something similar to ∇⍵-2 appears but with another symbol in place of ∇, does it parse the same way? (I'm not even certain that the ∇⍵-2 excerpt is a syntactic sub-unit that is valid on its own.)
- AlexCoventry 7y agoIn case anyone else is curious, but having trouble parsing that, "1≥⍵:⍵" means "return the input ⍵, for ⍵≤1", "⋄" is a statement separator, and "(∇⍵-1)+∇⍵-2" effectively means "otherwise, return fib(⍵-1)+fib(⍵-2)". ("∇⍵-2" means "∇(⍵-2)", because, as mentioned in the video, APL expressions are evaluated right-to-left.) The {} indicate that this is a function definition: https://www.gnu.org/software/apl/apl.html#Section-3_002e7 https://www.gnu.org/software/apl/apl.html#Section-3_002e7 My initial take on this, at least, is that it seems pretty reader-hostile. Maybe you get used to it, though.
- dTal 7y agoThat is truly beautiful. I already loved APL, from a distance as it were, but this gives me renewed respect for it.
- segmondy 7y agoIt's as reader hostile as mathematics symbol is reader hostile. It's not English, it's not meant to be read like a novel but to be read and understood like mathematics. One of the frustrating thing about programming in English like languages is that words might not mean what they claim to mean. Written language is very ambiguous. Nothing from stoping me from writing something as not_true = true; if (not_true) { ... }. or calling something manager or a process when it's neither. Easy to read and pronounce but harder to digest. The idea of APL is that once you understand the symbol like maths, it's unambiguous, if you can parse it, you can understand. There's no crazy naming to confuse you.
- AlexCoventry 7y agoProgramming is generally not mathematics, though. Usually, you're doing something considerably more complex, though also more concrete.