Hacker News new | past | comments | ask | show | jobs | submit login

The one liner is far less readable and under the hood it actually is worse: for each value in [0, m] you're iterating l and filtering it, so it's a O(n^2) code now instead of O(n). That mistake would be far easier to notice if you had written the exact same algorithm with loops: one would see a loop inside a loop and O(n^2) alarms should be ringing already.

Ironically, it's a great example of why readability is so much more important than conciseness and one liners.




I agree and despite beeing a fan (kind of a convert from OO) of FP I am often wondering about readability of FP code.

One idea I have is, that often FP code is not modularized and violates the SOLID principle in doing several things in one line.

there are seldom named subfunctions where the name describe the purpose of the functions- take lamdas as an example: I have to parse the lamda code to learn what it does. Even simple filtering might be improved (kinda C#):

var e = l.Filter(e => e.StartsWith("Comment"));

vs.

var e = l.Filter(ElementIsAComment);

or even using an extension method:

var e = l.FindComments();

sorry I could not come up with a better example- I hope you get my point...


True, it is computationally worse, though it's O(nm) so applying m at compile time to form a practical use as I used it will turn it into to O(n) in practice.

But that much is immediately obvious since it's mapping a filter, that is, has a loop within a loop.

I did consider the second one to also take quadratic time though. I forgot that in python getting list elements by index is O(1) instead of O(n) which is what I'm personally used to with lists.

It's also true that you can replace the filter with

  [ v | v <- l, v `mod` m == x ]
but that's not as much fun as

(x ==) . (`mod` m)

I just love how it looks and it doesn't personally seem any less clear to me, maybe a bit more verbose.


"I forgot that in python getting list elements by index is O(1) instead of O(n) which is what I'm personally used to with lists."

Have you considered that maybe this is a sign you're too deep into using impractical programming languages?

Cleanness for immutable data structures aside, linked list are a very poor way to store data given the way computer architectures are designed.


> Have you considered that maybe this is a sign you're too deep into using impractical programming languages?

“Languages that use ‘list’ for linked lists and have different names for other integer-indexable ordered collections” aren’t necessarily “impractical”.


> True, it is computationally worse, though it's O(nm) so applying m at compile time to form a practical use as I used it will turn it into to O(n) in practice.

Even applying it at compile time, it's still O(nm). You have to compute 'v mod m' for each possible value of v and m.

> But that much is immediately obvious since it's mapping a filter, that is, has a loop within a loop.

It's not immediately obvious because you have to parse the calls and see exactly where is the filter and the map.

    map(lambda x: do_some_things(x, another_param), filter(lambda x: filter_things(x), lst))
    map(lambda x: do_some_things(x, filter(lambda y: filter_things(x, y), another_list)), range(m))
versus

    retval = []
    for x in lst:
       if not filter_things(x):
          continue
       
       retval.append(do_some_things(x))
and

   for x in lst:
      filtered = []

      for y in in another_list:
         if filter_things(x, y):
             filtered.append(y)

     retval.append(do_some_things(x, filtered))
In the first case, you have to parse the parenthesis and arguments to see where exactly are the map and filter cals. In the second, you see a for with a second level of indentation.

> I just love how it looks and it doesn't personally seem any less clear to me, maybe a bit more verbose.

It doesn't seem any less clear to you because you're used to it. But think about the things you need to know apart from what a loop, map, filters and lambdas are:

- What is (x ==). Is it a function that returns whether the argument is equal to x? - What is '.'. Function composition? Filter? - Same thing with `mod` m. What are the backticks for?

Compare that with the amount of things you need to know with the Python code with for loops. For that complexity to pay off you need some benefits, and in this case you're only getting disadvantages.

That's the whole point of this discussion. Production code needs to work, have enough performance for its purpose and be maintainable, those are the metrics that matter. Being smart, beautiful or concise are completely secondary, and focusing on them will make for worse code, and it's exactly what happened in this toy example.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: