3 ms·
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 ⍵
by BenoitP 3y ago
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 https://jax.readthedocs.io/en/latest/jax.lax.html
- 3836293648 3y agoAPL 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
- gpderetta 3y ago> 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 https://github.com/KxSystems/kdb/blob/master/c/c/k.h
- yakubin 3y agoI love the “remove more clutter” comment. :D
- cmrdporcupine 3y agoAgree 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."
- martinsmit 3y agoThe 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-properties https://mlochbaum.github.io/BQN/spec/system.html#operation-p... [2]: https://saltysylvi.github.io/blog/bqn-macros.html https://saltysylvi.github.io/blog/bqn-macros.html [3]: https://mlochbaum.github.io/BQN/doc/rebqn.html https://mlochbaum.github.io/BQN/doc/rebqn.html [4]: https://github.com/google-research/dex-lang https://github.com/google-research/dex-lang
- nerdponx 3y agoYou might be interested in UIua, a stack-based concatenative array language inspired by BQN and others: https://www.uiua.org/ https://www.uiua.org/
- martinsmit 3y agoOh trust me, I am. The new code_report solution video on it convinced me to try it.
- tripdout 3y ago
- thesz 3y agoI 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.
- taeric 3y agoMore 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.
- _a_a_a_ 3y agoMy experience says totally otherwise. I've worked with both. Well written, well factored code is a dream to work with.
- taeric 3y agoWell 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 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."
- _a_a_a_ 3y agoIME, 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.