Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What to say, imagine my surprise seeing this on the first page of HN last night. Got my 15 minutes, I guess.

As is often the case, the responses contain a bunch of hateful stuff as well as people who actually try to engage with the ideas presented in a constructive manner. To state the obvious: I am not changing anything, so chill people.

Now to address some of the responses, starting with the best:

> I wanted to just drop a comment that I appreciate the time you took into this write up with code examples. It made understanding your POV very easy.

Thank you. Some of the comments lead me to believe we might have created a society where everything needs to be done in 140 characters. I am old school, arguments needs to be presented with enough background information for the reader to understand the perspective that led to the proposal or conclusion. Without that we are all just screaming things and waiting to see what sticks.

> APL is an almost perfect textbook example of write-only code.

Sure, just like math and musical notation are write-only. The only people who say stuff like this are those who don't know a thing about APL. There are two major APL compilers still on the market, the licenses for these cost in excess of $2,500 per year. If APL was "write-only" these two companies (IBM and Dyalog) would have shelved these products decades ago. The fact is that, while not mainstream (and for good reasons), APL is still in use and large codebases are being maintained and expanded. Historically this has mostly been in the financial sector.

Point of interest: My last large APL application was for a hardware/software system used during the race to decode the human genome. Among other things, my application interfaced with the hardware and was used to search for genomes in the sequences being produced. It also produced reports, graphs, managed the database, etc. The hardware portion was coded in Forth.

> APL's assignment operator is very strange to me

Thanks for a very detailed comment with code examples. I think I can help clarify the basic ideas.

The first thing to do is realize the assignment operator isn't passive but rather an active component of a statement being evaluated from right to left. That last part is important, APL evaluates from right to left, the only precedence rule being parenthesis are evaluated first. One could say indexing is also an exception but indexing "variable[23]" is a single monolithic expression that isn't separable, so it is evaluated as one item, not two.

So, if A and B are defined as vectors (APL's name for one dimensional arrays), each consisting of a few random values between 1 and 10:

    a ← 5?10  
    b ← 5?10
    a
    1 10 3 4 9 
    b
    9 5 6 1 4 
We can, for example, concatenate them like this:

    a,b
    1 10 3 4 9 9 5 6 1 4
Again, right-to-left evaluation says "take b, set it up to concatenate to something, ah, we are concatenating to a, another vector".

However, we can modify this process by giving the interpreter further instructions within the assignment. The simplest one is where we select, or index, the vectors and only grab specific elements to concatenate. I'll define a pair of new vectors to make this easier to see:

    c ← "ABCDE"
    d ← "abcde"
    c
    ABCDE
    d
    abcde
With this:

    c,d[1]
    ABCDEa

    c,d[2]
    ABCDEb

    c,d[2 5]
    ABCDEbe

    c[2 5],d
    BEabcde

    c[1],d 
    Aabcde

    c[2],d
    Babcde
The first few are the obvious cases, where we pull elements out of the right side vector and concatenate them to the left side vector. In the other cases we take the entire right side vector and concatenated to a subset of elements of the left side vector. I'd say this forms the basis for understanding the expressions you presented.

The above statements can be combined with assignment in order to do the work more efficiently, plain concatenation being the simplest case:

    e ← "mnlop"
    f ← "MNLOP"
    e
    mnlop
    f
    MNLOP

    e,←f
    e
    mnlopMNLOP
Again, right-to-left, we have vector "f", it will be concatenated to something, the assignment is a concatenation, it is concatenated and assigned to vector "e".

In other words, one can specify operations as part of the assignment. Because evaluation is from right to left, it stands to reason that the add-on operation has to be specified after you told the interpreter you are going to assign. This might be strange from the context of other paradigms but it makes complete sense once you grok the simple "everything is right-to-left" idea. If I were to propose how to read something like ",←" I would say "assign with concatenation"; "+←" would be "assign with addition".

We can do even more. It's easier to show this with multidimensional arrays:

    g ← 3 4 ⍴ "ABCDEFGHIJKL"
    h ← 2 4 ⍴ "abcdefgh"
    i ← 3 3 ⍴ "123456789"

      g
    ABCD
    EFGH
    IJKL

      h
    abcd
    efgh

      i
    123
    456
    789
The first statement reads something like this: Take the character vector "ABCDEFGHIJKL" we are going to reshape it "⍴" using a two dimensional numeric vector "3 4", thereby creating a 3x4 matrix and assign it to "g".

Note that "i" contains characters, not numbers, so if I try to add 1 to every value I get an error:

    i+1   
   DOMAIN ERROR
Now I can do a few things, for example:

Concatenate g and h along the first axis (they both have four columns):

      g,[1]h
    ABCD
    EFGH
    IJKL
    abcd
    efgh
Of course, all I have to do is add the assignment operator to change g:

      g,[1]←h

      g
    ABCD
    EFGH
    IJKL
    abcd
    efgh
As you can see, this is a natural extension of the syntax and the order of evaluation.

We can concatenate along the second axis if we use g and i:

      g,[2]i
    ABCD123
    EFGH456
    IJKL789
Assignment works just as well in this case:

      g,[2]←i

      g
    ABCD123
    EFGH456
    IJKL789
This syntax does have limitations. For example, what if I actually wanted to end-up with this?

    AEIae
    BFJbf
    CGKcg
    DHLdh
Well, we transpose the matrices during the concatenation, this works:

      (⍉g),[2]⍉h
    AEIae
    BFJbf
    CGKcg
    DHLdh
This does not work:

      (⍉g),[2]⍉←h
    SYNTAX ERROR
I don't recall why this is so. I think it has to do with starting to gobble-up piles of memory to keep intermediate results or something like that. You also end-up executing transpose (⍉) twice, which is inefficient. I don't remember.

This is a case where you have to resort to the simpler case:

      ⍉g,[1]h
    AEIae
    BFJbf
    CGKcg
    DHLdh
With assignment:

      g ← ⍉g,[1]h
      g
    AEIae
    BFJbf
    CGKcg
    DHLdh
In other words, concatenate along the first axis, transpose and then assign.

I got a little off track here with respect to the idea of using a different assignment symbol for Python but I thought your comment and implied question was one of the most interesting ones in the thread, which made it fun to address. I hope this helps. Here's a very useful resource:

https://www.dyalog.com/uploads/documents/MasteringDyalogAPL....

Ah, I do have to address one more:

> That's not on my keyboard.

Really people? It's 2019. I was typing APL characters back in the 1980's on DEC and Tektronix terminals and the IBM PC. Imagine the audacity of proposing that one can actually enter things other than ASCII or what's on the keyboard in 2019.

On the free NARS2000 interpreter you enter "←" very simply with "Alt [". In fact most APL characters are entered this way. The reshape operator, rho, "⍴", is entered using "Alt r". Not that complicated. I am sure this is well within the brain capacity of most mortals, it was so over 30 years ago.

Final thought: One of the interesting things about using APL long enough to internalize it (something like what happens when you don't think about reading musical notation any more and just see the music) is that you start thinking and seeing objects and their manipulation in your brain.

The analogy that comes to mind is what I do when I run SolidWorks. I can extrude, cut, scale, rotate, cut holes, create solids from rotated profiles, slice, animate and manipulate complex assemblies of three dimensional objects visually and with ease. The --imperfect-- analogy to conventional programming would be something like AutoCAD, which I have been using since version 1.0 in the dark ages. It's a flat 2D world. Yes, it can do 3D but the cognitive load and lack of tools makes it a terrible tool for working with three dimensional solid objects and assemblies.

Live long and prosper.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: