On Nov 6, 2019, at 21:53, Martin Euredjian via Python-ideas email@example.com wrote:
I've had this kind of a conversation with many people in the 30+ years since I learned APL and 20+ years since I stopped using it professionally. It has been my experience that people who have not had the experience rarely get it, and, sadly, more often than not, they become hostile to the implication that there might actually be a better way to translate ideas into computer executable code.
I haven’t used APL professionally, but I’ve heard Iverson talk about it, and read articles that are supposed to sell me on it, and I think I get the point of it. And the point is that it gets you about halfway to where Haskell does and then leaves you there.
In traditional languages you have to write loops and then turn your functions inside out. In Python/R/Mathematica/C++/etc. you can do things array-wise, but only the things the language/library designer thought of. (Well, you can use vectorize/frompyfunc/etc., which does have the right semantics, but it doesn’t look as friendly as the stuff NumPy comes with, and it’s slow.) GLSL has different limitations, and you often do have to think about the parallel “virtual loops” to do anything nontrivial. APL doesn’t have either of those problems; you can—and are actively encouraged to—think about how to combine operations independently from how to apply the combined operation.
But Haskell encourages that too—and further abstraction beyond it. Of course like J, its operators are strings of ASCII symbols (or identifiers in backticks), but that doesn’t change what the abstractions are, just how they’re spelled. For example, it’s cool that in APL I can lift + to sum just by writing +/, so I can sum an array of ints with +/x. But what if x is an array of bigints or fractions or decimal64s? As far as I know, there’s no way to implement such things in a way that + works on them. I know there’s a box operator that acts like an array by reading from stdin, but can I write something similar that reads from an open text file, parses it as CSV, parses the third column of each row as an int, and pass those ints to +/ too? What if I want to sum an array of maybe ints, or a maybe array of ints, and get back a maybe int? What if I want to pass around + or +/ or / as first-class objects? Can I even apply an operator to an operator, or do I only get second-order rather than arbitrarily-higher-order functionality? Can I write a new operator that unlifts and relifts any function in a way that turns this one from sum to running-sums?
Is there something about all of those limitations that crystallizes your thinking differently than having a more abstract and less restricted version of the same abstractions? That’s not inconceivable, but it doesn’t seem likely a priori, and I’ve never heard an argument for it, and none of the examples APL fans have shown me have convinced me.
And here’s the thing: sometimes Haskell is the right tool for the job, and even when it isn’t, learning it made me a better programmer even when I’m using other languages—but that doesn’t mean I want Python to be more like Haskell. (Well, maybe occasionally in a few minor ways, but I don’t want Python to be static-type-driven, or to be pure immutable, or to curry all functions and encourage point-free style, or to be lazy and make me trust an optimizer to figure out when to reify values, or to let me define hundreds of arbitrary operators, etc.) So, what’s different about APL that you want Python to be more like APL?