Preferences

MontyCarloHall parent
These are all great examples of the advantages of array programming syntax versus imperative scalar programming syntax, but do not IMO demonstrate the advantage of terse array programming syntax.

For example, the NumPy equivalents of your examples are not materially longer than their APL/J equivalents, but are easily readable even by people unfamiliar with NumPy:

> the average of a vector x; or the average of each column in a 2D matrix x

   x.mean(0)
or, to use your example verbatim,

  x.sum(0)/x.shape[0]
> flattens a recursive list

   x.ravel()
> name indexed by grading of ages

   name[age.argsort()]
Though for this application, you’d probably be using a dataframe library like Pandas, in which case this would be

   df.sort_values(“age”)[“name”]

beagle3
You didn’t address points I already raised about mean() - how does it handle an empty vector? How does it handle NaNs ? You have to read the documentation to figure that out. In K, the implementation is in front of your eyes; NaN handling follows from “over” / reduce / addition semantics; and empty vector from reduce and division by zero semantics. It is all consistent by construction, and follows from basic properties. The same cannot be said about mean() or sum().

The call to .ravel() is strictly less powerful than ,// which would flatten a matrix, but also a lisp/xml style recursive list structure. And it is the actual implementation, not some weird name! It is “join over until convergence”.

With respect to sorting, in K you would also likely use the built in relational operator “?” (select).

Notice how you need to import pandas and numpy, and then know their docs well to find the routines you want and how they behave in edge cases? And that’s in addition to actually knowing Python?

K has all of that built in. You just need to know the basics (which takes more work than knowing Python well, admittedly). Most from there is derived by construction. It does have some 80 or so non-trivial primitives, but then you need much fewer libraries, often none.

(And, that’s not a for/against thing, but … in case you wonder, the K executable does that in about 200K binary without dependencies; REBOL achieves similar terseness of final programs by completely different means and philosophy, and also packs that into a 400K executable)

RodgerTheGreat
The point is that every idiom beagle3 noted is a simple and straightforward combination of general building-blocks, whereas nearly all of your "equivalents" are a one-off special-cased feature or function that needs to be learned on its own. The power and expressiveness of APL-family languages comes from the fact that they have a very small number of well-chosen parts that can be combined in flexible ways. Those patterns of combination become a higher-level vocabulary that fluent programmers grasp at sight, much as experienced readers of English learn to recognize the shapes of entire words at a time. This type of visual pattern recognition is facilitated by brevity.

APL-style idioms are not at all comparable to functions on a class or within a library, because idioms are self-describing in their entirety, requiring only an understanding of the primitive operators of the language, whereas a named function obscures and subordinates detail.

This item has no comments currently.