1 comment

[ 0.16 ms ] story [ 20.6 ms ] thread
When there are multiple code smells, which should have preference?

FWIW, the "straightforward approach" is invalid when the list contains only one element, which helps support the argument that special cases are code smells.

However, the suggested solution - padding - assumes that such solutions are possible. That is, it assumes that there is enough memory to duplicate the array, and introduces a full copy as all the data is transferred, potentially twice. The result might be measurably and noticeably slower. There's also the overhead of instantiating the iterator object via map.with_index, and the double array indexing for each value - which may be slow depending on how the object implements array indexing.

I consider those to also be code smells, and worse code smells than special casing.

The following Python code also has special cases, because of the two 'yield' statements. However, it has none of the above mentioned downsides of the proposed proposed solution:

  def neighbor_sum(values):
     value_iter = iter(values)
     left = 0
     mid = next(value_iter)
     for right in value_iter:
        yield left + right
        left, mid = mid, right
     yield left
As far as I can tell, it produces the same results. It should also be faster and lighter in memory use than the equivalent Python implementation of the proposed solution.

The 'Down with evens' example is also going to be slower than it "should" be, because it creates and destroys unneeded temporaries. The argument is that "conceptually map is a better fit", but as a Python user I would implement it like:

  def down_with_evens(data_list):
    for x in data_list:
      if len(x) % 2 == 0: # even
         yield [x[0]]
         yield x[1:]  # or 'del x[0]; yield x' to match the original
      else:
         yield x
Isn't that clearer, and without the code smell of unneeded object creation causing performance slowdowns? Does Ruby have something comparable?