Hacker News new | ask | show | jobs
by chriswarbo 1310 days ago
Here's some made up code:

  pruned = map(
    # Remove all elems whose foo is less than the number of elems
    lambda elems: list(filter(
      lambda elem: elem.foo < len(elems),
      elems
    ))
  )
Now let's say we want a running total of all the foos. We can insert an expression to do this:

  total_foos = [0]
  pruned = map(
    # Remove all elems whose foo is less than the number of elems
    lambda elems: list(filter(
      lambda elem: (
        # Add elem.foo to our total_foos accumulator
        total_foos.append(total_foos.pop() + elem.foo),
        elem.foo < len(elems)
      )[-1],
      elems
    ))
  )
  total_foos = total_foos.pop()
This is rather awkward and "non-Pythonic"; ideally we would use 'total_foos += elem.foo', but that can't exist in a lambda. Hence:

  total_foos = 0
  
  # Have to define this outside the map, since it's a statement
  def checkAndAccumulate(elems):
    """This checkAndAccumulate function is just a wrapper, for closing-over
    the elems variable (since it's not in-scope outside the map call).
    Returns the actual checking+accumulating function."""
    def checker(elem):
      """The actual function we want to filter with"""
      total_foos += elem.foo
      return elem.foo < len(elems)
    return checker

  pruned = map(
    # Remove all elems whose foo is less than the number of elems
    lambda elems: list(filter(
      checkAndAccumulate(elems),
      elems
    ))
  )
1 comments

I can only quote OP on this:

> But if you feel the need to transform simple linear code into a map of higher order functions because of some abstract benefits you're probably doing stuff that's too easy for you and you should get your mental challenge from solving a more difficult problem instead.

This code is only complicated because you insist on following some abstract ideal. The actual way to solve this in python is:

  total_foos = sum(elem.foo for elem in elems)
  pruned = [e for e in elems if e.foo < len(elems)]
Which is shorten than even your first code sample. If you directly translate your last example into sensible python, you get a nice example of some "simple linear code":

  total_foos = 0
  pruned = []
  for elem in elems:
      total_foos += elem.foo
      if elem.foo < len(elems):
          pruned.append(elem)
The existence of statements in python clearly stands in the way of achieving ideals of pure functional programming. But I think aiming for such ideals is the exact opposite of the point OP was making.