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

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.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: