|
From: | Elias Mårtenson |
Subject: | Re: [Bug-apl] Non-bug: Help comparing solutions |
Date: | Thu, 6 Mar 2014 10:41:36 +0800 |
> Jokes aside, while I'm all in favor of such extensions for tacitI feel the same way. Lexical scoped d-fns are what keeps APL a modern language. They are much easier and safer to work with, not to mention more powerful. I heard on a recent conference video that younger APL programmers don't even bother looking at traditional ∇ functions (I certainly subscribe to this view.)
> programming (composition, currying, hooks/forks/trains, as in NARS2000,
> NGN, newer versions of Dyalog, J), I think proper lambdas are a much
> more important and fundamental issue.
Even the classic example of a fork (+/÷≡) is harder to read than its functional version {(+/⍵)÷≡⍵} and it goes downhill from there with longer trains. But maybe it's just me being unfamiliar with the syntax.
They are expressions made by juxtaposing functions by themselves, without any explicit arguments. They were invented in J to allow for a programming style called function-level or point-free programming (or "point-less" as Wikipedia suggests.) They were then ported to Nars2000 to experiment with them in APL.
Two juxtaposed functions (f g) are called a "hook" and if I'm not mistaken, they behave like the classical jot composition f∘g which in most interpreters means {⍺ f g⍵}. Compare it to "hoof" composition f⍥g as implemented in Nars2000 (or "paw" f⍤g in Sharp APL) which means {(g⍺) f g⍵}, leaving aside considerations about rank, which complicate matters. For completeness, "hoof" f⍥g in Sharp APL means something else entirely: {f ⍺g⍵}. Notice how the explicit functional syntax {...} is always the clearest and less ambiguous one.
Three functions (f g h) are called a "fork" and behave as {(⍺f⍵) g ⍺h⍵}. Of all these, the fork is the only one that has a basis in traditional usage, where functions are sometimes applied between other functions in a kind of "shorthand" to yield new ones: f + g traditionally means the function {(⍺f⍵) + ⍺g⍵}. This isn't necessarily a good thing though, given that APL was invented to overcome the idiosyncrasies of traditional math notation.
Longer sequences are called "trains", but IMHO they get harder to read as their length increases. Notice the different purpose of functions in odd and even positions in the trains, but also the qualitative difference between dyadic trains with odd and even numbers of functions:
Monadic trains:
(X A) ≡ {⍵ X A⍵}
(B X A) ≡ {(B⍵) X A⍵}
(Y B X A) ≡ {⍵ Y (B⍵) X A⍵}
(C Y B X A) ≡ {(C⍵) Y (B⍵) X A⍵}
(Z C Y B X A) ≡ {⍵ Z (C⍵) Y (B⍵) X A⍵}
(D Z C Y B X A) ≡ {(D⍵) Z (C⍵) Y (B⍵) X A⍵}
Dyadic trains:
(X A) ≡ {⍺ X A⍵}
(B X A) ≡ {(⍺B⍵) X ⍺A⍵}
(Y B X A) ≡ {⍺ Y ( B⍵) X A⍵}
(C Y B X A) ≡ {(⍺C⍵) Y (⍺B⍵) X ⍺A⍵}
(Z C Y B X A) ≡ {⍺ Z ( C⍵) Y ( B⍵) X A⍵}
(D Z C Y B X A) ≡ {(⍺D⍵) Z (⍺C⍵) Y (⍺B⍵) X ⍺A⍵}
I hope you can see the "point-less" programming style :-)
[Prev in Thread] | Current Thread | [Next in Thread] |