Hacker News new | past | comments | ask | show | jobs | submit login
On being startled by a programming language (bbot.org)
66 points by sbierwagen on March 17, 2011 | hide | past | favorite | 49 comments



J is awesome. GPL'd J is even better!

Some of us are trying to organize our efforts here: https://github.com/openj/core

We don't intend on mucking with the code much at this point, just patching together a better build system, etc.


I think I'm more amazed at the C code. Is that obfuscated or a decompiled dump? Or is that how the core of J is really written?


Hah! That is how the code is really written. It's... a unique style, shared amongst the APL languages.

I'm pretty sure there are about two people that can read and write that fluently: Roger Hui and Arthur Whitney.


As a wholly unaffiliated, self-selected, and entirely unofficial spokesperson, I'm happy to bestow this lifetime achievement award on behalf of the IOCCC.


People who like APL do not often code with readability as their number 1 priority. In fact, to code in APL one must have an outright disdain for the idea that someone else could easily understand their code.


No, we just have a different idea of what's readable. APL was created to have a mathematical notation that made problem solving easier. Don't believe me? See Iverson's Turing Award lecture,"Notation as a Tool of Thought" (http://www.jsoftware.com/papers/tot.htm).

"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." - "A Conversation with Arthur Whitney" (http://queue.acm.org/detail.cfm?id=1531242)


APL is actually not inherently so bad, because at least the operators have some vague relationship to what they're doing and are all distinct. I can't read J at all because in attempting to embed the APL operator space in ASCII they went in for multiple token operators that can be modified (so =, =., and =: are all different, and actually quite different IIRC).

A better way of doing this is Fortress, which tries to use mathematical notation when possible but doesn't try to compress it as small as possible.


With that kind of attitude, they might enjoy programming in Brainfuck or Malbolge even more.


Begging your pardon, you're doing so out of ignorance. An entire programming ecosystem -- a brilliant one, one of the very most impressive -- has been built on top of what you are denigrating. Scour through searchyc looking for past threads on APL/K/J and you'll find the arguments all repeated on multiple occasions, including many instances of the same but-this-isn't-what-I'm-used-to rush to judgment that always, unfortunately, comes up in droves.


You're conflating the implementation of an environment with the value of the environment itself. Did you read the C code? It is terribly difficult to follow, does not follow C formatting idioms, and makes frequent use of macros that further obfuscate what is going on. Example:

  #define DECLG  V*sv=VAV(self);A gs=sv->g;  \
                 AF g1=gs?VAV(gs)->f1:0,g2=gs?VAV(gs)->f2:0
Judging the quality of this code says nothing about the language and environment that this code provides.


From the coding conventions for Kona (http://github.com/kevinlawler/kona/wiki/Coding-Guidelines), an open-source implementation of K 3.2 that I've been contributing to lately:

    This is a very unusual style of C
"The unusual appearance is a side effect of writing C as concisely as possible. There are great benefits to writing code as concisely as possible. Someone familiar with the style can read and comprehend the code much faster than they would be able to with traditional code. It also creates a discipline that reduces bugs. Some of the benefits will not be apparent until you try it. Some of the downsides of the style are inaccessibility and a steep learning curve."

You get used to code like that, and often, doing it that way makes sense. I first encountered it learning to read this short prototype interpreter (http://nsl.com/papers/origins.htm) by Arthur Whitney, which very strongly influenced the programming style in the J codebase.

As gruesom notes, this discussion has already happened numerous times in the HN archives. Your reaction is the APL equivalent of going, "OMG! Parens!!!!1!" when introduced to Lisp code.


Fair enough, although I've read many threads on APL-derived languages over the years on HN, but I somehow missed the discussion of the C runtime implementation.


AFAICT, the implementations have usually been closed-source (with the exception of A+ (http://www.aplusdev.org/), which is GPL'd; Arthur wrote it before K), and most research on APL implementation is locked behind the ACM paywall.

I suspect part of the style comes from APLers typically being mathematicians as well as programmers, and drawing more from mathematics than typical "software engineering best practices" style.


Then, forgive me for harping on this, how could this discussion have already happened numerous times on HN? And by "this discussion" I mean the C style used to implement APL-derived languages, not the style one uses to write programs in APL-derived languages.


They've mostly involved the "J Incunabulum" prototype and A+. See e.g. http://news.ycombinator.com/item?id=2178177 .


Hi Scott. I don't exactly agree, because the terseness and lexical density of the C code are the same qualities as cause people to recoil from APL/J/K programs as well (http://www.nsl.com/k/s/s.k). The implementation and language are cut from the same cloth. This of course is not always true (i.e. your point holds much better in the general case) - but it is true in this world, where program brevity and regularity are so highly prized.

Let's note that the payoff for departing from the mainstream in this way is not small: these languages achieve abstractive (compositional) power and elegance without sacrificing efficiency. Those two things are incompatible in nearly every other programming context -- so much so that it's a truism that higher-level code is shorter but slower, lower-level code is faster but more verbose. Yet here they happily co-exist.


silentbicycle's examples and points have actually made me come around somewhat.

But there is a key difference between the terseness and density of APL-derived languages and the C implementation of the runtime: in the actual languages, the semantics of the language are well defined and enforced by the compiler. C is a free-for-all. So while there is discipline behind the C code - and I can see that it mimics the language it implements - it must be self discipline. That makes it more dangerous, and objecting to that is not the same as objecting to the APL family of languages themselves.


Forgive me, I think we've had a misunderstanding. To my mind, the IOCCC is a contest where very smart people work very hard to bend C as far as it will go to come up with very clever programs. The fact that something as impressive as J is implemented like this blows me away, and while I would never want to (nor ever could) work in the codebase myself, I think it's wonderful.


Forgive me back. I was writing more hastily than I usually try to do and being kind of a grouch about it.


I've seen some threads on APL, but I've never seen other languages used with APL-level compression. Are there really other threads about this? I'm not sure what to search for on searchyc.


Try any of these: apl iverson k kona whitney j hui incunabulum

(That one-page J interpreter is sometimes called the "J Incunabulum".)

See e.g. http://news.ycombinator.com/item?id=1458016 http://news.ycombinator.com/item?id=266982 http://news.ycombinator.com/item?id=697501 http://news.ycombinator.com/item?id=2176980


That is one of the most frustratingly idiotic things I have ever seen.

Any incentive I had to try this language is now gone and I want to erase the memory of its construction from my mind.


How could you look at an APL-family language and then be totally outraged that the implementation took quite a bit stylistically from the language itself?


Conventional C style is there to improve its readability and maintainability. Applying APL style to C code is sort of like trying to use Russian grammar with English vocabulary, you might be able to puzzle out the meaning, but it is a stupid waste of time.


Actually, given that a substantial part of the codebase involves looping simple operators over vectors, it makes sense to use macros to make the looping implicit.

Code like this needs to be read more slowly than usual, because unlike much C code, the information level isn't low enough that you can read it lines at a time. Math papers have all these weird sigma symbols and stuff, too; you can't read just them as fast as you would read "for (i=0; i<N; i++) {" for the millionth time.

Likewise, rather than writing "for (i=0; i<N; i++) {" yet again, K just calls that ' and moves on. In the source, there's a macro called DO, which is used extensively. DO(N, Blk) -> for(i=0, int _n=N; i<_n; i++) { Blk } . The APLs are about having a notation that doesn't constantly get in the way of thinking about your actual problem.


In practical implementations we call this code write-only.

It's funny that you bring up mathematical notation because mathematical notation is completely optimized for write-only. Mathematics is so obsessed with one letter variable names that they had to gather letters from other alphabets to continue their opaque tradition.


I find mathematical notation to be very read-friendly. Reading a paper from an unfamiliar field can be tough, as knowledge of the standard notation is typically assumed (as is the case when reading code from an unfamiliar programming language).

Mathematical "code" isn't usually meant to be read without the surrounding variable and notation declarations, for example "Let x be ..." or "where • is the ... operation". If those are provided, short variable names and terse notation allow for the intent to be presented clearly, without it being obscured by line-length restrictions and a limited number of generic constructs (eg. for-loops instead of the summation operator).

That said, I'm finding this C implementation of J to be pretty cryptic. Of course, that's no reason to dismiss the J programming language itself.


It looks as though Kevin Lawler can hold his own in that style, too. https://github.com/kevinlawler/kona/blob/master/k.c


Btw, is this related in anyway to Arthur?


Apparently Arthur Whitney wrote a one-page interpreter of an APL dialect in C (in the same style!) which inspired Ken Iverson to write J.

http://keiapl.org/rhui/remember.htm#40


He is also the author of the K language.


That's how it's really written. Take a look at the source of A+ sometime.


Thanks for that! I've been trying to use the libraries found at http://www.jsoftware.com/trac/base/browser/trunk (svn co http://www.jsoftware.com/svn/base/trunk/), but I can't seem to be able to load anything:

  % jconsole
  |file name error
  |       0!:0 y
     load 'packages/misc/fndisplay.ijs'
  |value error: load
  |       load'packages/misc/fndisplay.ijs'
(I tried with absolute paths too)

Any idea what I might be missing? And do you know the license of the libraries?


I would like to coin a phrase: "seduced by syntax".

I think humans LOVE syntax; and syntax is often loveable, crystallizing a new viewpoint into a linguist pattern that allows this viewpoint to be diffused by our amazing hardwired capabilities for language. J does that.

That being said, sometimes being seduced, while REALLY FUN for a little while, turns out to REALLY MESSED UP in the long run. I think J and APL are like that too -- just break up with him, really....

For another metaphorical take: I think Python and C are like English -- boring, with a lot of fun syntax stripped out, but very, very useful. C++ is like Mandarin -- completely complicated, but so much literature and history is written in it that you have to take it seriously. Shell is like the pidgin languages. And J/APL ... they are like Quileute (the language spoken by Jacob-the-Werewolf's tribe): completely difficult, arcane, counter intuitive, and only spoken by like six other weirdos (ie don't bother).

All these languages are seductive, though.

J programmers love to exchange emails like "I found a way to calculate pi to the 80th decimal with only 4 characters" ... as if that is remotely useful. We have J code in use in our office -- its fun, if you like speaking Klingon, but it is a complete waste of time and sweat for any pragmatic applications. If you want to do complex weird matrix stuff in a few lines, learn linear algebra and tensor operations for chrissake, which actually have some utility in the real world. And don't be fooled by APL/J types telling you their language is mathematical -- it isn't, in the sense that you can't actually derive new results with it; it is just difficult (good math makes thing easier).

Sorry for the rant. I wish the damn language would disappear, and we could remember it wistfully like SNOBOL, Ada, SAS, and other bad experiments in seductive syntax.


Syntax to me is superficial. What APL/J/K are doing is much deeper: programs are short sequences of composable operators.


I get your point, but syntax ceases to be superficial if it prevents you from expressing what you want to say cleanly. As a daytime Java programmer, discovering the freedom from syntax that Lisps allow you has been revelatory.


I quite agree. It was revelatory for me in the same way.


Math invented composable functions (sin(sqrt(blah)) -- extending it to operators is fun, but not really very important.

Oh -- I would respectfully hazard that syntax for you (and for me!) is no more for superficial than the blue eye shadow on the girl in my 10th grade English class, if you get my drift. ;)


I'm trying to figure out what is so startling about this, actually. The { function just seems to return the element at the given index, or if you pass in a collection of indices, maps that operation onto the collection. That is convenient operator overloading but not mind-blowing.


True, that is what's happening. The cool thing is that dimensional (in J terms, it's 'rank') overloading is inherent to the language.

Most operators have implicit dimensional looping or respond different to differently ranked inputs.

Take for example integers (i.):

       i.3
    0 1 2
       i.3 3
    0 1 2
    3 4 5
    6 7 8
(That's kind of a dumb example, but I think it at least hints at the expressive power of rank.)


Other than using an operator for a function name, there's no real rocket surgery in this post:

  >>> def index(x, y):
        'Dyadic function indexes y by x'
        return [y[i] for i in x]

  >>> p = list(range(22))
  >>> shuffle(p)
  >>> p
  [1, 20, 19, 15, 9, 14, 6, 8, 2, 4, 16, 18, 10, 3, 0, 13, 12, 11, 7, 17, 5, 21]
  >>> index(p, p)
  [20, 5, 17, 13, 4, 0, 6, 2, 19, 9, 12, 7, 16, 15, 1, 3, 10, 18, 8, 11, 14, 21]
  >>> index([1]*22, p)
  [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20]
  >>> index(p, [1]*22)
  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]


Yesterday I was testing something in ruby. Basically the return value was a constant * rand. Yeah, 0.6360787621690106 and 0.6360787023690106 were the two results. I was like what's going on? until I noticed the middle of the answer was different. Felt like nearly winning the lottery.


I'd FUUUUUU on that.


I remember APL from my college years. APL is the archetypal write-only programming language.

Even with 20-to-1 comment-to-code ratio, it was easy to get confused with code written the previous morning. By you.

From what I see, the most important development is using plain ASCII. Too bad it's still unpronounceable. Dictating APL code to another student was endless fun. We even invented our own names for some of the symbols...

Having said that, APL was exquisitely powerful and concise. Yet, I have to wonder if there is space for an exquisitely concise write-only computer language today.


Haha, I remember feeling the same way about K many years ago.


I've been taken aback by some of the concepts of Haskell recently as well. Hooray for obscure but insanely powerful languages!


Intentional pun in the blog? "This shit is crazy! Let me show you a log."


:>


OMG! Zoinks!




Join us for AI Startup School this June 16-17 in San Francisco!

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

Search: