Hacker News new | past | comments | ask | show | jobs | submit login

Well APL is great but it is write-only. Also naming is hard, but in APL it is very easy: you just don't do it. What does the following do?

    program ← {⊃1 ⍵ ∨.∧ 3 4 = +/ +⌿ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵}
Libraries in other languages deal with arrays just fine, and can solve actual problems at internet scale. Like numpy/jax, or pytorch, which will compile your code to clusters of TPU/GPUs. Most of the useful primitives of APL are present in these libraries (iota, reshape, reduce, etc[1]). The function composition primitives in APL are fine from a theoretical viewpoint, but I can't help feeling like I'm dealing with some obfuscation language crafted by academia to protect some fiefdom. Is it really that interesting to have a primitive for swapping arguments? Isn't that in the domain of conventions? APL was used by algorithmic trading companies for interviewing; just like Google wants you to go through Leetcode only to never use that kind of programming again.

Also APL/BQN/I/J/K all lack an auto-differentiation primitive, which is sort of a shame for 'functional' languages. Functions are mathematical objects too!

But if you just want a code golf session, then I guess APL is just fine. It also may improve your functional abstraction thinking.

/yelling at cloud, I'll go back to my cavern now

[1] https://jax.readthedocs.io/en/latest/jax.lax.html




The lack of an AD primitive is something I've discussed with the creator of BQN, coming from a JAX world I really miss it and feel that it's such an obvious feature, especially in a language which has a way to turn a tacit function into its AST[1], which has been used for symbolic differentiation[2]. Going from symbolic to reverse-mode AD is not much of a leap and users can define their own primitives with ReBQN[3].

I see what you mean by obfuscation, but I think that it's one of those things that feels really hard and stupid until you start being able to do it really quickly. When you learn a foreign language, you first read letters, then words, then sentences because you become accustomed to larger pieces of the language that you can predict what's coming next without reading it. A similar sort of thing happens with APL/BQN, you read letters (primitives), then you begin to recognise words (small, commonly used groups of primitives), then you see larger patterns which look like magical incantations to an inexperienced user.

These "words" are (typically) tacit phrases, many of them only existing due to specific primitives like swap. Once I used BQN to golf, I started wishing Julia had a swap for operators i.e.

  -(3, 5) = -2
  swap(-)(3, 5) = 2
I won't defend these languages to the death, but they are fun to puzzle your brain with in codegolf. Maybe Dex[4] will go somewhere too.

[1]: https://mlochbaum.github.io/BQN/spec/system.html#operation-p...

[2]: https://saltysylvi.github.io/blog/bqn-macros.html

[3]: https://mlochbaum.github.io/BQN/doc/rebqn.html

[4]: https://github.com/google-research/dex-lang


> I started wishing Julia had a swap for operators

You can define one pretty easily:

    julia> swap2(f::F) where F<:Function = (a, b) -> f(b, a)
    swap2 (generic function with 1 method)

    julia> swap2(-)(3, 5)
    2
(Perhaps you meant you wished it was pre-defined with the language, I understand the slight friction of having to define things for every project; this is just making sure you know it can be done pretty easily.)


You might be interested in UIua, a stack-based concatenative array language inspired by BQN and others: https://www.uiua.org/


How do you start to learn a language like this? Are there any good resources for example leetcode-type problems to solve with Uiua?


Oh trust me, I am. The new code_report solution video on it convinced me to try it.


I don't know a bit of APL, but I see numbers 3 and 4 and suspiciously looking pair of triples of -1, 0 and 1.

Thus, this program of yours has game of life step function somewhere there.

The "writeonlyness" is in the eyes of beholder, and I am almost not joking - we see better what we expect to see. It is possible to determine algorithms by their structure which rarely changes much betweend different languages.

But, I have 34 years of experience in software development and I often delve into very strange languages out of curiosity and to find what does unify them or make them special for some particular tasks.


APL was not designed to protect some fiefdom. It was just the notation they used on the blackboard during lectures and for that purpose it's fine. Then someone implemented it.

And later array languages have mostly abandonned the crazy names in favour of actual words, at least as far as I've seen


> And later array languages have mostly abandonned the crazy names in favour of actual words

Sharing this without comments:

https://github.com/KxSystems/kdb/blob/master/c/c/k.h


I love the “remove more clutter” comment. :D


Agree with all your points, but I guess one advantage I can see to being more strictly "array purist" is that it forces one to write the whole program in such a way that SIMD & GPU etc optimizations would apply. These days dealing with things in array-sized chunks and avoiding excessive branching has huge advantages, performance wise, but most languages (especially OO languages) herd you into conditional branches on individual scalars, all over the place.

Obviously not applicable for the vast majority of applications, but something to think about: that it would be nice to see array-orientation further up the stack than just "compute this bulk data set on the GPU/TPU."


More code is "write only" than we'd care to admit. And most code that embraces that winds up more stable than you'd expect.

Note that this does not mean that the code is irreplaceable. It just means that you are almost forced to care only about two things: the overall input, and the overall output of the code in question.

This "focus on the input/output" extreme is embraced, at large. We often take it to scatter your program into a ton of easy parts where you can do this with relatively little effort at read/write time. But, zoom out and all of those little parts are almost always just as hard to work with as some of the dense "write only" code that people love to complain about.


My experience says totally otherwise. I've worked with both. Well written, well factored code is a dream to work with.


Well written code is a dream to work with, pretty much period? Such that, I don't really disagree; but this general thought exercise is dominated by people talking past each other.

Don't get me wrong, I am not aiming for the entire program to be line noise. I've seen more attempts to make the command line argument parsing "clear and easy to read" such that "no mistakes could possibly creep in" than I'd care to admit, though.

Probably the best example of what I mean here, though, is summed up in the quote from https://gigamonkeys.com/book/a-few-format-recipes.html regarding FORMAT. "While FORMAT's control strings can be cryptic, at least a single FORMAT expression doesn't clutter things up too badly."


IME, pretty much, period, yes.

I didn't provide evidence because I didn't have any except from my experience which I ask you to take at my word, and I'll take you on your word that's something I'm unaware of what can happen to undo the value of well structured code in a way I've not encountered.

Your example is something I understand (though I'm not a Lisp programmer) but I'm certainly not allergic to a few judicious DSLs to clean things up.

Without evidence on either side there's no point continuing this but it was a nice answer, thanks. I wish we could discuss this in person.


I doubt we are in heavy disagreement. My point was not meant for whole programs to be done in this way. I am a heavy advocate for judicious use of the likes of XPath (or JMESPath or JSONPath/whatever) at the border to deconstruct things. Similarly, having a query language instead of manually learning how to do all of the necessary merge and sort operations for many things makes a ton of sense.

Does this mean I think DSLs are a panacea? No. Not at all. And I meant my point to be that we are in agreement that well written code is better in pretty much all cases. Be it well factored, or well whatever.

Would indeed be a fun thing for more conversations. I am always amused and amazed at how many strawman programs people have had the misfortune of working with.




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

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

Search: