Live data from Hacker News

What learning APL taught me about Python

mathspp.com

41–50 of 104 posts

Re: What learning APL taught me about Python

#41
post #39
post #33

Earlier quoted context omitted.

functools.partial is currying, right?

No, it’s partial application. Currying is when a 1-arity function either returns another 1-arity function or the result.

hmm... that just sounds like a specific case of recursive application of partial functions? At least that's how I interepret the wikipedia explanation:

"As such, curry is more suitably defined as an operation which, in many theoretical cases, is often applied recursively, but which is theoretically indistinguishable (when considered as an operation) from a partial application."

(while I see partial as having value, I'm struggling to see if currying would really be a useful addition to a scripting language)

Re: What learning APL taught me about Python

#42
> Another big thing that APL made me realise is that the Boolean values True/False and the integers 1/0 are tightly connected

Amen! It's of course also a C language tenet, and a great one. Life is so much simpler and more flexible when true and false are 1 and 0. It drives me crazy when I need to use a language where the logical operators only work on bools and the arithmetic only on ints, or some coercions work and others don't. When I incorporate somebody else's code into mine, first thing I get rid of is anything called "bool", a completely useless type. (as a nice side effect, that frees up the bool keyword for Boolean sets, which are quite useful)

a disappointment with unix is that process retval has this a bit backward, 0 is success, nonzero is failure (probably because errno does want for more bits than a singleton) but it's easily enough remedied with a !

I did love everything else about APL for the brief time I used it long ago (except the difficulty of entering the symbols)

Re: What learning APL taught me about Python

#43
post #14

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 lis…

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

#44

Earlier quoted context omitted.

Python's lack of multi-line anonymous functions is a hindrance to using it as a functional language, IMO.

Multi-line lambdas are fine: Python will accept newlines in certain parts of an expression, and you can use '\' for others; e.g. f = lambda x: [ x + y for y in range(x) if y % 2 == 0 ] >>> f(5) [5, 7, 9] Lambdas which perform multiple sequential steps are fine, since we can use tuples to evaluate expressions in order; e.g. from sys import stdout g = lambda x: ( stdout.write("Given {0}\n".format(repr(x))), x.append(42…

Neat. I tried it with print(), works fine.

Don't need return in a lambda. Assignment now has the walrus. Leaves raise and few other odds and ends.

Do believe you've cracked it! Don't think I'll use it much, but you never know... in a pinch.

Re: What learning APL taught me about Python

#45
post #14

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 lis…

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

#46
post #14

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 lis…

> 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

#47
post #32
post #5

I find that the more language you learn the better you can utilize all of them. Also, Python is a wonderful functional language when used functionally.

It is a poor functional language. List comprehensions (from Haskell) are nice, but the rest is garbage. Crippled lambdas, no currying, "match" is a clumsy statement, weird name spaces and a rigid whitespace syntax. No real immutability.

I use the toolz package for currying and a few other conveniences.

That plus named tuples and a little discipline gets me 80+% of the benefits of pure functional.

The biggest thing to me wasn't in your list: lack of tail call optimization means you have to be a bit careful about where you use recursion.

I personally think long anonymous functions are an anti-pattern, naming your functionality is great for readability. I learned this from Wolfram language which makes heavy use of anonymous functions, I would often find myself returning from lunch to find my code which was perfectly clear that morning had become unintelligible. Today I try to limit anonymous functions to re-ordering arguments or "picking" functions that pull simple values out of more complicated data structures.

Re: What learning APL taught me about Python

#48
post #42

> Another big thing that APL made me realise is that the Boolean values True/False and the integers 1/0 are tightly connected Amen! It's of course also a C language tenet, and a great one. Life is so much simpler and more flexible when true and false are 1 and 0. It drives me crazy when I need to use a language where the logical operators only work on bools and the arithmetic only on ints, or some coercions work and…

* This statement is supported by the competitive programming community.

Re: What learning APL taught me about Python

#49
post #14

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 lis…

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"?
Post reply on HN