6 ms·
I wonder if array languages will find wider popularity some day with a bit more verbose notation. Take “Array Indexing” (#29): {(,⍺)[(⊂⍴⍺)⊥¨⊃∘.,/⍵]} Or “I
by evincarofautumn 8y ago
I wonder if array languages will find wider popularity some day with a bit more verbose notation. Take “Array Indexing” (#29):
{(,⍺)[(⊂⍴⍺)⊥¨⊃∘.,/⍵]}
Or “Inverted Table Index-Of” (#31):
(⍉↑x⍳¨x) ⍳ (⍉↑x⍳¨y)
These could be written:
{(reshape lhs)[(enclose shape lhs)
polynomial each disclose
outer product reshape reduce rhs]}
(transpose take x index each x)
index (transpose take x index each y)
Same terms, just with searchable words instead of symbols. (Don’t mind the specific words—I’m not much of an APL user!) It definitely sacrifices some important aspects of APL, but in exchange I think it gains something in terms of accessibility by explicitly writing the pronunciations you might have in your head anyway when reading & writing the symbolic notation. It also encourages extracting reusable named definitions instead of repeatedly writing “idioms”.
- beagle3 8y agoThere is some experience with this in the K community, and the answer is "it does not gain accessibility"; and "extracting reusable definitions" goes against the spirit of APL, at least for the simple stuff. Everyone focuses on the syntax because that's the first thing you see, but it's just the tip of the iceberg. The real problem is that you have to think differently, and a weird representation actually HELPS you start thinking differently. My favourite two examples (K syntax - K is of the APL family) are: maximum subarray sum, written in K |/0(0|+)\ and in english "max over 0 (0 max plus) scan"; And flatten, written in K ,// and in english "join over converged". They are both good examples of K's orthogonality (which is shared by APL and J), and of the fact that the english doesn't make them more readable if you don't already have the right mindset. K has a verbose english syntax called Q. People who grok the APL mindset, quickly drop Q for K (which is terser and uses symbols), and people who don't rarely find Q more palatable than K.
- dang 8y agoThe version of this in the Lisp family is the many attempts to replace s-expressions or "drop the parens". The original notation always bounces back unscratched because it's a deep fit for the mindset.
- jim-jim-jim 8y agoThat's very true. I'm having fun trying to wedge my brain into an APL-shaped hole right now because I did it with Lisp before and know it eventually pays off.
- RodgerTheGreat 8y agoA few of my favorite longer phrases: expand a run-length encoded list: ,/#/' maximum depth of a nested list: #,/\ shape of a rectangular nested structure: -1_#:'*:\ count of each group: #:'=: which in k5 and newer leads nicely to a way to find the mode of a list. k5 made group produce a dictionary instead of a list of lists, and the grade operators are overloaded to sort dictionary keys by values, producing a list: *>#:'=:
- Avshalom 8y agoI like the permutation example, make a n^n array of 1...n there by ending up with n choose n with replacement, create a boolean mask of which ones have all n numbers and return. There was a post here last week about BEAM needs an apl that pointed out the basic idiom of APL is take an array make a boolean mask then select on that mask which I thought was a very straight forward explaination of how APL differs from Matlab or Numpy. And it is a very different approach: make everything take what you want vs make exactly and nothing more than what you want.
- carapace 8y agoYou actually get used to the "line noise" pretty quickly and then you can read it. It's weird but true.
- infinite8s 8y agoI wonder if it is the same transition that an illiterate adult goes through if and when they finally learn to read. Most of us probably don't remember the feeling of doing that when we were young children.
- eggy 8y agoCheck out Q'Nial for something like what you are asking for here. It is an array language, but uses more verbose function names: https://github.com/danlm/QNial7 https://github.com/danlm/QNial7
- mncharity 8y ago> languages [...] more verbose notation With IDEs, and soon 3D, programming UX design space extends far beyond language syntax. Concision is important for APL-style abstraction-by-eyeball. So one might enrich tooling instead. "Tell me about this expression... What does it mean? Highlight related expressions. What idioms are being used? Are there any relevant design notes? Where is it in the dataflow graph? ..." We've not yet been discussing it much, but with VR/AR and cloud, the constraints under which programming languages have evolved for the last several decades are about change. Perhaps unicode-enabled concision will be part of that.
- geocar 8y ago> It definitely sacrifices some important aspects of APL It sacrifices the most important aspect: The notation. From A Conversation with Arthur Whitney[1] BC To ask a slightly broader question, what is the connection between computer language and thought? To what degree does our choice of how we express software change the way we think about the problem?* AW I think it does a lot. That was the point of Ken Iverson's Turing Award paper, "Notation as a Tool of Thought." I did pure mathematics in school, but later I was a teaching assistant for a graduate course in computer algorithms. I could see that the professor was getting killed by the notation. He was trying to express the idea of different kinds of matrix inner products, saying if you have a directed graph and you're looking at connections, then you write this triple nested loop in Fortran or Algol. It took him an hour to express it. What he really wanted to show was that for a connected graph it was an or-dot-and. If it's a graph of pipe capacities, then maybe it's a plus-dot-min. If he'd had APL or K as a notation, he could have covered that in a few seconds or maybe a minute, but because of the notation he couldn't do it. Another thing I saw that really killed me was in a class on provability, again, a graduate course where I was grading the students' work. In the '70s there was a lot of work on trying to prove programs correct. In this course the students had to do binary search and prove with these provability techniques that they were actually doing binary search. They handed in these long papers that were just so well argued, but the programs didn't work. I don't think a single one handled the edge conditions correctly. I could read the code and see the mistake, but I couldn't read the proofs. Ken believed that notation should be as high level as possible because, for example, if matrix product is plus-dot-times, there's no question about that being correct. [1]: https://queue.acm.org/detail.cfm?id=1531242 https://queue.acm.org/detail.cfm?id=1531242
- evincarofautumn 8y agoSure, I’ve read Iverson’s paper. I think the notation is perhaps what enabled him to come up with what I feel is the important thing: the semantics. I care a lot about function-level programming, tacit programming, implicit iteration, and dimension-agnostic code; I don’t really care for APL/J notation specifically, and not because of the funny character set or terseness, but because it’s not compositional. Changing the symbols out for words wouldn’t help much with that; I just think it would make it more popular.
- tigershark 8y agoI just upvoted you, but I don’t think it works like that. It’s like to judge how you can paint Da Vinci’s “Monna Lisa” by using more or less strokes than necessary. Probably you can do it but it’s not the same thing the author intended. Art, like programming, is entirely subjective. And, as far as I know “J” objective was not very dissimilar than yours, unless I badly misjudged what you are trying to achieve.
- cousin_it 8y agoEnglish identifiers solve half the problem. The other half is figuring out how the code maps to a tree. For example, in "transpose take x index each x", what is applied to what? The best solution for me is to use "f(x,y)" syntax instead of "f x y" etc. Can you rewrite your examples using "f(x,y)" syntax?
- ratboy666 8y agoReads left to right. Executes right to left. APL doesn't have precedence rules. 5 times 4 plus 1 is 25 (1 plus 4) times 5. Turns out reading left to right works. So the tree is trivial.
- cousin_it 8y agoThe tree isn't trivial. For example, +/x is over(plus,x), not plus(over(x)). And our example certainly isn't transpose(take(x(index(each(x))))), so what is it?
- bakul 8y agoUsing a Scheme like syntax, */x is ((over +) x). That is, over is a higher order function, yielding a new fuction.
- ratboy666 8y agoIt is trivial -- mostly, and for IBM APL2 and GNU APL. I have quoted the GNU APL manual below. Note that J, K, etc. are richer, and have different rules. APL is standardized (ISO), but GNU APL attempts to be IBM APL2 and ISO compliant (ISO/IEC 13751:2001). Note that each (¨) is an operator -- there is no ambiguity. ⍴¨(1 2 3)(1 2)(1 2 3 4 5) 3 2 5 which (I suspect), you would rather each(rho, ((1 2 3) (1 2) (1 2 3 4 5))) So -- your example would be (better) transpose(take(each(index, x), x)) Quoting the GNU APL manual: "There are 4 APL symbols / ⌿ \ and ⍀ that can be functions or operators, depending on their context (i.e. depending on the APL tokens left of them). Neither the ISO standard nor the otherwise excellent IBM APL2 language reference manual explain the rules that decide whether, for example /, should mean ’function compress’ or ’operator reduce’. In simple cases the meaning of / is obvious: +/B means ’operator reduce’ while 1/B means ’function compress’. " " an become more complex if index brackets or parentheses are involved. The algorithm used in GNU APL for classifying / and friend is (simplified) this: 1. / ⌿ \ and ⍀ are tokenized as operators 2. Scan the tokenized statement from left to right to find / ⌿ \ or ⍀ 3. If a / ⌿ \ or ⍀ is found, go backwards until a constant, or a function, or a user-defined name is found: 3a. if a constant, a function, or a user-defined name is found then →4 3b. if ) is seen then skip over it, That is, a parenthesized expression is entered. 3c. if ] is seen then skip until the corresponding [ is found, That is an index list or axis is skipped over. 3d. otherwise: SYNTAX ERROR 4. decide the role of / \ ⌿ or ⍀ based on the kind of token that was found in 3a: 4a. function: leave / as operator as initially tokenized 4b. constant: change / from operator to function (compress) 4c. see below This works fine except in case 4c. which cannot be resolved at ⎕FX time. For this case we introduce the following convention: A user-defined name is assumed to be a function (and hence / is an operator) unless the name (and nothing else) is enclosed in parentheses. For example: A / B ⍝ A is function, therefore / is operator (A) / B ⍝ A is value, therefore / is function This rule is moderately compatible with ISO and APL2; in APL2 (A) would be redundant parentheses so in that case there would be a small incompatibility between GNU APL and IBM APL2. "
- segmondy 8y agoYou can assign a name to each of those symbols if you want and have something equivalent to what you just wrote. tranpose=:⍉ take:=↑ index=:⍳ each=:¨ done, now I can write (⍉↑x⍳¨x) as (transpose take x index each x) But the entire idea of APL is notation as a tool of thought. Would you write read your maths as five plus twenty is equals to twenty five or 5 + 20 = 25? Would you rather read music with it's musical notiation or quarter note at middle C, quarter note at middle E, etc? The entire idea of APL is that we read and write algorithms the way we read mathematical and musical notes.
- FPGAhacker 8y agoThat’s a pretty good analogy, the 5 + 20 example. By using abstract symbols, it encourages one to skip the internal verbalization and go straight to the concept. Pretty neat. But in the article, they use symbols that I don’t have on my keyboard. I guess one would learn the combination for such symbols and become fluent to the point that it didn’t matter. For example, I don’t think of the individual letters when I’m typing. Although my highschool typing class strongly encouraged doing so. I believe that was more for maintaining a rhythm, however.
- Jtsummers 8y agoEarlier this year I took a deep dive into APL (something I'd been meaning to do for a while). With Dyalog APL and the APL mode in emacs, typing these things in is pretty easy and becomes natural if you're already a touch typist. For instance, iota is just `.i`, rho is `.r`, etc. Some are more natural (like that) others are arbitrary but logically consistent, like take and drop are next to each other on the keyboard. After a few days I felt like I could type most programs without having to think about where keys were. Admittedly, I've lost it all now since I haven't touched it for a couple months. If I actually stuck with it for more than the 4-6 weeks I did I imagine I wouldn't have lost it so quickly.
- untangle 8y ago> APL mode in emacs, typing these things in is pretty easy...iota is just `.i`, rho is `.r`, etc. ...and iota is just `i and rho is `r in the Dyalog editor. So non-emacs folks can play too.
- jonahx 8y ago> I wonder if array languages will find wider popularity some day They already have: Numpy [0] is essentially a subset of J/APL ported to python objects. While it's a practical and useful library, it's also nowhere near as elegant as J. The notation does matter. [0] http://www.numpy.org/ http://www.numpy.org/
- fantispug 8y agoAlso R and MATLAB/octave are array based languages too. You may consider Fortran one too. But none of them have things like dyads.
- Avshalom 8y agoThe thing is if you get rid of the pressure to be notation you get rid of the pressures that makes APL what it is. You could definitely make an array language with words but you'd end up with something more like Factor with it's cleave/spread/apply combinators (you work on a factor inspired concatenative language right?).
- evincarofautumn 8y agoYeah, that’s fair. I don’t imagine such a language would be well liked by the APL/J/K purists (“You’re missing the point!”), just that it could bring the school of thought to the masses—and maybe as a side effect, encourage people to check out the “real deal”. More of a marketing decision than a technical one. You wouldn’t necessarily have to use explicit dataflow combinators in a wordy array language, but if you did, you might as well go all-in on function-level programming and do a concatenative language. And yeah, I’m working on a Kitten, a CPL with static types—apart from the paradigm and some similar standard APIs, it doesn’t actually have a whole lot in common with Factor; the feel I’m going for is more like postfix OCaml/Rust, whereas Factor is pretty Lispy/Smalltalky.
- kd0amg 8y agoI don’t imagine such a language would be well liked by the APL/J/K purists (“You’re missing the point!”) Meh. I'm not interested in code golf. I find it mostly disappointing that discussions of APL and its descendants rarely include anything of substance about the array programming model. Everyone argues about whether the constant-factor size change from glyphs/words is worth it, but what I actually find interesting is the flexible code reuse you get from having every function automatically work on arbitrarily large data.
- evincarofautumn 8y agoExactly, I think the semantics & interactive mode of programming have a lot of value, and it’s a shame they seem to get less attention than they deserve just because the notation is inscrutable to newcomers.
- madhadron 8y agoI think this is a difference in background. A programmer I am friends with found Haskell a nightmare to read because (we finally realized) it looked more like math than ALGOL. Because I my background I have parsers for both approaches that are equally strong, whereas his parser for ALGOL like syntax was strong and his one for math was much weaker. Whenever we crossed that notational divide and switched mental parsers, the incidental mental load he was subject to skyrocketed.