Live data from Hacker News

What learning APL taught me about Python

mathspp.com

31–40 of 104 posts

Re: What learning APL taught me about Python

#31
This is completely off topic (though possibly still on the topic of maximal readability) but the correct way to express this logic is as follows:

  age >= 18
If your code is specifically about the magical age of adulthood then it ought to include that age as a literal, somewhere.

It becomes more obvious when you consider replacing the inline literal with a named constant:

  CHILD_UPTO = 17  # awkward
compared with:

  ADULT = 18  # oh the clarity
My fellow turd polishers and I would probably also add a tiny type:

  Age = int
  ADULT: Age = 18  # mwah!
(The article was a good read, btw.)

Re: What learning APL taught me about Python

#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.

Re: What learning APL taught me about Python

#33
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.

functools.partial is currying, right?

Re: What learning APL taught me about Python

#34
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…

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

#36
post #2

The only thing this does for me is ask why its not named count instead of sum.

It is summing but being used for counting (in imitation of the same style from APL) via punning on True/False as 1/0. Not what actually happens but conceptually: ages = [17, 13, 18, 30, 12] sum(age > 17 for age in ages) => sum([False, False, True, True, False]) => sum([0, 0, 1, 1, 0]) => 2 # via conventional summing Since True and False are 1 and 0 for arithmetic in Python, this is just a regular sum which also happe…

yeah if i ready the line using "sum", I would be expecting the result 48 (18+30) not 2

Re: What learning APL taught me about Python

#37
post #23
post #8

Earlier quoted context omitted.

I don’t think you can do that with a generator expression. You would have to write: sum(1 for age in ages if age > 17)

If you're going to go that route, I think this makes more sense: count_over_17 = [age > 17 for age in ages].count(True)

For a very large sequence traversing it to build a list and then traversing the list to do something you could do in one traversal without creating a list may be undesirable.

Re: What learning APL taught me about Python

#38
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…

If ages is a numpy array instead of a list: (ages > 17).sum()

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

#39
post #33
post #32

Earlier quoted context omitted.

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.

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.

Re: What learning APL taught me about Python

#40
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.

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),
      stdout.write("Mutated to {0}\n".format(repr(x))),
      len(x)
  )[-1]

  >>> my_list = [1, 2, 3]
  >>> new_len = g(my_list)
  Given [1, 2, 3]
  Mutated to [1, 2, 3, 42]
  >>> new_len
  4
  >>> my_list
  [1, 2, 3, 42]
The problem is that many things in Python require statements, and lambdas cannot contain any; not even one. For example, all of the following are single lines:

  >>> throw = lambda e: raise e
    File "", line 1
      throw = lambda e: raise e
                        ^^^^^
  SyntaxError: invalid syntax
  >>> identity = lambda x: return x
    File "", line 1
      identity = lambda x: return x
                           ^^^^^^
  SyntaxError: invalid syntax
  >>> abs = lambda n: -1 * (n if n ", line 1
      abs = lambda n: -1 * (n if n >> repeat = lambda f, n: for _ in range(n): f()
    File "", line 1
      repeat = lambda f, n: for _ in range(n): f()
                            ^^^
  SyntaxError: invalid syntax
  >>> set_key = lambda d, k, v: d[k] = v
    File "", line 1
      set_key = lambda d, k, v: d[k] = v
                ^^^^^^^^^^^^^^^^^^^^
  SyntaxError: cannot assign to lambda
  >>> set_key = lambda d, k, v: (d[k] = v)
    File "", line 1
      set_key = lambda d, k, v: (d[k] = v)
                                 ^^^^
  SyntaxError: cannot assign to subscript here. Maybe you meant '==' instead of '='?
Post reply on HN