Все решения, использующие zip
и т. Д., Делают тонны ненужных выделений. Как функциональный программист, вы хотите привыкнуть не выделять ресурсы, если только вам это не нужно. Распределение стоит дорого, и по сравнению с распределением все остальное бесплатно. И распределение не просто отображается в «горячих точках», которые вы найдете с помощью профилировщика; если вы не обращаете внимания на распределение, это убивает вас везде .
Теперь я согласен с комментаторами, что удобочитаемость - самая важная вещь . Никто не хочет быстро получать неправильные ответы. Но в функциональном программировании очень часто случается, что существует множество решений, одинаково читаемых, некоторые из которых выделяют, а некоторые нет. Очень важно выработать привычку поиска читаемых, нераспределяющих решений.
Вы можете подумать, что оптимизатор избавится от распределений, но вы будете правы только наполовину. GHC, лучшему в мире оптимизирующему компилятору для Haskell, удается избежать выделения пары на элемент; он объединяет композицию filter
- zip
в foldr2
. Распределение списка [1..]
сохраняется. Теперь вы можете не думать, что это так плохо, но потоковое объединение, которое является текущей технологией GHC, является несколько хрупкой оптимизацией. Даже экспертам сложно точно предсказать, когда это сработает, просто взглянув на код. Более общий момент заключается в том, что когда дело доходит до критического свойства, такого как распределение, вы не хотите полагаться на причудливый оптимизатор, результаты которого вы не можете предсказать . Пока вы можете писать свой код одинаково читабельным образом, вам гораздо лучше никогда не вводить эти распределения.
По этой причине я считаю решение Нефрубыра, использующее drop
, безусловно, наиболее убедительным. Единственными значениями, которые выделяются, являются именно те cons-ячейки (с :
), которые должны быть частью окончательного ответа. Кроме того, использование drop
делает решение более простым, чем просто читаемым: оно кристально чистое и очевидно правильное.