Talk:Articles/J -- a Glimpse of Heaven
The First Step is Easy
NOTE[1]: APL indents by 6 spaces. J indents by 3 spaces. This makes the formatting of examples look slightly different, but the formats are in fact the same on each page: J and APL versions. Ian Clark (talk) 07:02, 23 May 2018 (UTC)
NOTE[2]: The J Copula ( =: ) happens to be the reverse of the Pascal assignment: := which evokes the Backus-Naur (symbolic logic) equivalence: ::=
First Program
There are two methods of defining a Verb:
- Compose it tacitly from other Verbs: a so-called tacit definition
- Define it explicitly by a "program": a so-called explicit definition.
Ian Clark (talk) 07:27, 4 June 2018 (UTC)
Why "tacit"? Tacit has to do with keeping quiet. With Verb composition we keep quiet about the Verb arguments (i.e. Nouns), only talking about the Verbs we want to stick together. Computer scientists call this sort of thing functional programming.
Ian Clark (talk) 03:42, 23 May 2018 (UTC)
First Program: tacit definition
A tacit definition will look something like this:
Average =: +/ % #
read:
- apply +/ to the left argument of Average (…or the right argument, if there isn't a left argument),
- apply # to the right argument of Average,
- divide one result by the other by inserting % between them.
Ian Clark (talk) 03:47, 23 May 2018 (UTC)
First Program: explicit definition
An explicit definition will look something like this:
Average =: verb define (+/y) % (#y) )
Average is the program name.
- y (a Noun) represents the right argument
- x (a Noun) represents the left argument (but Average has no use for it)
- the last Noun to be computed is returned at the end.
The right parenthesis ) marks the end of the definition, i.e. the end of the program.
NOTE: I've chosen to use Tally (#) instead of Shape Of ($), the proper counterpart of rho (⍴) in APL. Why? Because that's usually how Average or Mean is defined.
Ian Clark (talk) 07:34, 4 June 2018 (UTC)
First Program: when to use tacit definition and when to use explicit definition?
Tacit definition is good for utility Verbs, which are usually well-tested and you hardly ever want to re-program them.
Explicit definitions (since they work mainly with Nouns, not Verbs) are good for binding your program to the current values of caches and flags.
As a bonus to beginners, they also look more like conventional programs (but a lot shorter!) To beginners coming from C/C++ (say) they are easier to re-program.
Experienced J programmers know how to turn an explicit definition into a tacit one – and even back again! And even how to mix the two methods.
Ian Clark (talk) 03:51, 23 May 2018 (UTC)
Index Origin
Legrand's examples all use the APL setting: ⎕IO=1 which happens to be the default.
J, on the other hand, operates exclusively in Index Origin 0, equivalent to: ⎕IO=0
The result is that comparable expressions (involving array indexes) will inevitably differ by 1.
⍳⍴Val 1 2 3 4 5 6 7 i.#Val 0 1 2 3 4 5 6
Ian Clark (talk) 06:40, 23 May 2018 (UTC)
Two observations concerning Verb Rank
(contributed by Martin Kreuzer)…
1. Using verb rank ("1) to address the table row-wise
'aeiouy' e. Towns NB. this doesn't work 0 'aeiouy' e."1 Towns NB. comparing each table entry separately 1 1 1 0 1 0 1 0 1 0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 1 1 0 0 0 0 +./ 'aeiouy' e."1 Towns NB. ORing the results 1 1 1 1 1 0
2. "Flattening-out" the matrix using Ravel (,) shows the effect of Fill
# Towns NB. there are 5 table entries 5 # , Towns NB. of length 10 each 50 , Towns NB. due to Fill (with blanks) Martigues Paris StrasbourgGranville Nantes < , Towns +--------------------------------------------------+ |Martigues Paris StrasbourgGranville Nantes | +--------------------------------------------------+ 'aeiouy' e. , Towns NB. these blank are of no concern here 1 1 1 1 1 0
…(moved from main body of article) Ian Clark (talk) 07:10, 4 June 2018 (UTC)
Simplify and modernize
Why trouble with i.@:# when we can use I. Val > 35
(Val>35)#i.#Val 1 2 4
--David Lambert (talk) 13:43, 4 June 2018 (UTC)
David Lambert makes an excellent point, and his code is better in every (practical) way than the original.
So why do I think it belongs here, and not back in the body of the original treatment, to (quote) "simplify and modernize" it?
Not because I'm enamoured of the phrase I used to emulate Bernard Legrand's corresponding APL construct, but because I needed to strictly preserve the integrity of Bernard's original treatment in what is intended as a J "parallel text".
Chris Burke originally wrote: However, while it was written specifically for APL, it applies equally well to J, and might just as well have been "J - a Glimpse of Heaven".
Taking this assertion absolutely literally, I wrote my translation. But in doing so I was compelled to stick to the (obviously) common ground between APL and J, steering clear of constructs where J has chosen to improve on its parent language – APL.
Or more accurately: APL as it was when Bernard wrote his article.
Morten Kromberg, who owns Dyalog APL, has written to me to point out that APL too has advanced since Bernard's article, and my J "translation" unfairly portrays APL in an antiquated light. I am compelled to agree, though that wasn't my aim. But my intent was – and still is – to be scrupulously fair to Bernard's treatment (which I consider a masterpiece of technical exposition), even at the cost of being unfair to APL. Especially in its modern manifestation as Dyalog APL.
David Lambert makes the opposite point: that I'm being unfair to J in choosing to follow Bernard's APL code so closely. But I needed two sets of matching code samples which (a) allow a student of either language to compare them primitive-by-primitive, seeing past the syntactic sugar to their underlying commonality, and (b) publishing code which runs on current releases of J and Dyalog APL respectively, which I was able to verify at the time.
In passing, Morten and I concluded that we must cooperate in an upgrade of Bernard's article which makes the latest Dyalog APL lock-step with the latest J, showing off the modern features of each. Such as verb rank, which both languages now flaunt. This will happen when we both have time to spare. Ian Clark (talk) 03:11, 13 January 2019 (UTC)
"MUMMY"
R=:((V i.V)=i.$V)#V.
And who will believe me when I say that this expression does not require any “reading” or “analysis” for an J-er. It is read and understood instantly, as a whole, just like the word “MUMMY” is fixed in our mind without having to read and interpret it letter by letter, as a small child does it.
Well, I, for one, needed to do the reading and analysis.
If you pass in i. 10
, it sure seems to be an identity function, but... okay:
(V i. V)
returns the first index at which each item of V appears.i.$v
(when v is a vector) counts up to the length of v, which basically gives an index of the vector.- So when the index is the first index, return 1, else 0. In other words, mark the first occurrence of each item in the list.
So ((V i. V)=i.$V)
is "nub sieve", which we would normally write as ~: v
.
((V i. V)=i.$V)#V
, then, is "nub". Again, we're more used to seeing it as ~. v
.
Note: I think i.#v
is probably a more accurate translation than i.$v
, because this verb as written does not behave the same for arrays that are not vectors, whereas i.#v
works for any rank.
But I think is a bad example entirely for J simply because we're *not* used to seeing such an idiom spelled out, since J has evolved to contract it even further. It's actually become example of an expression that is way too verbose. :)
--Michal Wallace (talk) 20:45, 12 August 2021 (UTC)
- But the target wiki page has a restricted mission: to celebrate a milestone contribution to the APL world by Bernard Legrand, and extend it to J by means of a parallel page. The operative word here is parallel, because that is a much more useful attribute (in this pair of pages) than topicality or completeness. So I recommend the original APL and J versions stand. Ian Clark (talk) 09:04, 20 November 2021 (UTC)