News for hackers. Stuff that matters.
Re:What Learning APL Taught Me About Python by tcoff91 on Wednesday August 16, 2023 @05:41PM (#37154253)
I feel like this kind of operation on a list feels more naturally expressed by filtering the list and taking the length of the filtered list.

Like this line of JS feels so much easier to read than that line of python:

    ages.filter(age => age > 17).length
Directly translating this approach to python:

    len(list(filter(lambda age: (age > 17), ages)))
Although a better way to write this in python I guess would be using list comprehensions:

    len([age for age in ages if age > 17])
which I feel is more readable (but less efficient) than the APL inspired approach. Overall, none of these python versions seem as readable to me as my JS one liner.
Re:What Learning APL Taught Me About Python by WhiteRice on Wednesday August 16, 2023 @06:29PM (#37154742)
I didn’t see it in the article so I thought I would add,

The actual apl implementation: +/age>17

Apl implementation of taking the length(shape) of the filtered list: ⍴(age>17)/age

Re:What Learning APL Taught Me About Python by Jtsummers on Wednesday August 16, 2023 @06:32PM (#37154765)
It's in there but near the end (80% or so of the way down the page). The article would benefit from moving that to the top and drawing the comparison to the APL code earlier.
Re:What Learning APL Taught Me About Python by adalacelove on Wednesday August 16, 2023 @06:33PM (#37154783)
If ages is a numpy array instead of a list:

    (ages > 17).sum()
Re:What Learning APL Taught Me About Python by dTal on Wednesday August 16, 2023 @06:50PM (#37154922)
Numpy is something close to APL semantics with Python syntax. There's no doubt it was heavily inspired by APL. One could argue that numpy's popularity vindicates the array model pioneered by APL, while driving a nail in the coffin of "notation as a tool of thought", or APL's version of it at any rate. Array programming has never been more popular but there's no demand for APL syntax.
Re:What Learning APL Taught Me About Python by adalacelove on Thursday August 17, 2023 @02:06AM (#37157837)
I think the key to array programming success was due to the possibility of having fast interpreted languages for numerical computing. I'm very used to programming in array languages (Matlab, Python, Julia and even Mathematica has lot of vectorized ops) and still I think a lot in terms of for loops.
Re:What Learning APL Taught Me About Python by sideshowb on Thursday August 17, 2023 @02:34AM (#37157994)
This. Ideally we'd have jitted python loops be efficient. I love array syntax for simple examples but for more complex ops a loop is often clearer.
Re:What Learning APL Taught Me About Python by TheRealKing on Thursday August 17, 2023 @11:56PM (#37171242)
Numpy's vectorized syntax is inspired by Fortran.
Re:What Learning APL Taught Me About Python by jph00 on Wednesday August 16, 2023 @06:44PM (#37154880)
It feels more natural to you because of familiarity. However, if you've learned Iverson Bracket notation in math (https://en.wikipedia.org/wiki/Iverson_bracket) then the APL approach will probably feel more natural, because it's a more direct expression of the mathematical foundations. Of course, the actual APL version is by far the most natural once you're familiar with the core ideas: +/ages>17
Re:What Learning APL Taught Me About Python by lmm on Wednesday August 16, 2023 @07:30PM (#37155266)
I felt the same way about Rust's .await and .?; I think we're gradually converging on the idea that postfix operators are the right way to do 1-argument functions. I'm not remotely convinced that RPN is a readable idea in general, but when we have a pipeline rather than a tree, writing it left-to-right is the winner.
Re:What Learning APL Taught Me About Python by Bostonian on Wednesday August 16, 2023 @07:45PM (#37155367)
In Fortran it's

   count(ages > 17)
and storing the ages > 17 is done with

   is_adult = pack(ages, ages > 17)
Re:What Learning APL Taught Me About Python by veber-alex on Wednesday August 16, 2023 @07:49PM (#37155408)
> Obviously if the function is on a hot path iterating and summing with a number is far more efficient versus filtering.

I got curious and checked this in Rust, the generated assembly is the same!

https://rust.godbolt.org/z/jhGWdYPz1

Re:What Learning APL Taught Me About Python by proto_lambda on Thursday August 17, 2023 @03:15AM (#37158283)
Because you're not actually creating a filtered list, you're just filtering an iterator.
Re:What Learning APL Taught Me About Python by nonameiguess on Thursday August 17, 2023 @11:10AM (#37162887)
Neither of your examples is doing what the parent suggested as an alternative, which is simply looping and counting rather than creating an anonymous function to repeatedly call. I doubt this makes an enormous difference in practice, but you can see your generated assembly doing all the argument passing and stack frame setup, which is extra instructions compared to just straight looping and counting.
Re:What Learning APL Taught Me About Python by jodrellblank on Wednesday August 16, 2023 @08:14PM (#37155584)
The blog starts out with mentioning other reduce operations in Python: 'prod from the math module; min; max; any; all; and "".join'. In APL those are:

    ×/ product reduce
    ⌊/ min reduce
    ⌈/ max reduce
    ∨/ logical OR reduce (any bool set)
    ∧/ logical AND reduce (all bools set)
    ,/  catenate reduce (join without spaces)
These all show a pattern of connection clearly where the Python names don't, that they are related operations; that suggests that you could put any function on the left or any kind of array on the right and see what happens. And they work over multidimensional arrays - and you can swap / for ⌿ to reduce down columns instead of accross the rows.

Your rewritten Python and JS, by showing the operation as length instead of sum, and making a shorter filtered list, hide the connection even further instead of helping to reveal and clarify it.

> "which I feel is more readable (but less efficient) than the APL inspired approach"

I know how to read it, but just look at:

    age age ages age

    len age for age in ages if age
what's readable about so much repetition, what's readable bout having to spot the single character plural change in the middle of 8 short words?

    ([>])
that's more symbols than the APL one has, the language people reject because of the heavy use of symbols(!). Why does the [] indicate loopy-listy code but so does 'for'? In PowerShell arrays have a property .Count to use instead of Length - what's readable about counting the number of ages by indirectly looking at the length of something? Is this "it's readable because I'm familiar with it" rather than "because it's objectively readable"?
Re:What Learning APL Taught Me About Python by kwertzzz on Thursday August 17, 2023 @04:22AM (#37158698)
Interestingly most (if not all) python examples also work in julia. Instead of using sum one can also use count, which might be more readable:

julia> count(age > 17 for age in ages)

Or even shorter:

julia> count(ages .> 17)

Under the hood many of the functions are implemented using the reduce function (similar to / in APL):

julia> reduce(+,ages .> 17)

I think many languages in data science have been influenced by APL. But sometimes this influence come from an intermediate language like matlab.

Re:What Learning APL Taught Me About Python by leephillips on Thursday August 17, 2023 @12:41PM (#37164406)
Yes. One of the “repercussions” of the author’s experience with APL might have led to him recoiling from the verbosity of his Python examples and exploring languages, like Julia, that can get closer to the APL spirit.
Re:What Learning APL Taught Me About Python by lionkor on Thursday August 17, 2023 @02:46AM (#37158065)
Doing @WalterBright's job for a second to let you know that in the D language, given a function that is defined as taking, say, a list as the first argument, it can be called either

    myfun(list)
or

    list.myfun()
and this applies without exception. This means a lot of C-library code gets easier to read when used from D:

    Vector3 vec = (Vector3){ 1, 2, 3};
    Vector3 result = Vector3Add(vec, vec2);
becomes

    auto vec = Vector3(1, 2, 3);
    auto result = vec.Vector3Add(vec2);
I know its slightly off topic, but I want more people to use D, I really prefer it to C, C++ and Rust.
Re:What Learning APL Taught Me About Python by tcoff91 on Thursday August 17, 2023 @02:25PM (#37165948)
I love D, learned it back in high school, but unfortunately it just seems like D is one of those great languages that just isn't going to take off. It just doesn't have a big enough champion to bootstrap a thriving large community that would make more people want to learn it and more companies adopt it.

On its technical merits, one of the best languages out there. It gives you insane performance but is so much easier to learn and write than C++ or Rust.

Re:What Learning APL Taught Me About Python by marko-lev on Thursday August 17, 2023 @04:23AM (#37158714)
I like to leverage some FP to bring readability to python

  from toolz import curried, pipe

  pipe(ages,
       curried.filter(lambda age: age > 17),
       list,
       len)
This way you can follow - vertically - what happens, where, and why.

You can make your own pipe function to avoid 3rd party dependencies

  import functools
  pipe = lambda *args: functools.reduce(lambda acc, el: el(acc), args)
Re:What Learning APL Taught Me About Python by alanbernstein on Thursday August 17, 2023 @04:51AM (#37158934)
I feel like the numpy version is most concise, most readable, and most array-ish:

np.sum(age>17)

(Assumes age is a np.array)

Re:What Learning APL Taught Me About Python by RojerGS on Thursday August 17, 2023 @05:33AM (#37159265)
Yes, this is VERY close to the APL way: +/ages>17

OP here; maybe I'll add a comment to the article to make the comparison between NumPy and APL for this expression. Thanks!

Re:What Learning APL Taught Me About Python by leprechaun1066 on Thursday August 17, 2023 @07:28AM (#37160006)
APL (along with Matlab, K, Mathematica, etc.) was one of the influences for NumPy anyway.
Re:What Learning APL Taught Me About Python by drcongo on Thursday August 17, 2023 @04:57AM (#37158978)
Your list comprehension is how I would naturally write this, and to me seems the most readable - it's almost like an English language sentence. The sum example in the article would probably be my second choice.
Re:What Learning APL Taught Me About Python by Expurple on Thursday August 17, 2023 @08:20AM (#37160468)
Yes. This gets even better with Haskell's partial application:

    length $ filter (> 17) ages
And that's ignoring the fact you can also

    count pred = length . filter pred
    
    count (> 17) ages
Re:What Learning APL Taught Me About Python by theodpHN on Thursday August 17, 2023 @08:33AM (#37160594)
IMO, SQL is more straightforward if not quite as terse:

select count(*) from ages where age > 17

Re:What Learning APL Taught Me About Python by redpenguin101 on Thursday August 17, 2023 @09:25AM (#37161193)
"Easier to read" is relative. For someone used to lisp syntax, the Python looks quite natural - only the parens are in the wrong place.

E: And I guess the lambda and explicit list-cast too. cf.

    (count (filter #(> % 17) ages))
Re:What Learning APL Taught Me About Python by banashark on Thursday August 17, 2023 @01:57PM (#37165598)
The concise reduce is fairly small:

    ages.reduce((a, c) => (a + (c > 18)), 0)
Though usually in production code you'll see this as something like

    ages.reduce((acc, cur) => {
      return acc + c > 18 ? 1 : 0
    }, 0)
Which creates some more noise but ups readability