Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
xs = range(limit) и чистить результат xs перед каждым start = time(). Потому как тогда одинаковые входные данные, да и всегда отрабатывем garbage переменной xs снаружи замера. xsin = range(limit)
xs = None
start = time()
xs = [checker(x) for x in xsin][::-1]
print('inline for:', time() - start, [xs[0], xs[-1], len(xs)])
xs = None
start = time()
xs = list(map(checker, xsin))[::-1]
print('map:', time() - start, [xs[0], xs[-1], len(xs)])
xs = None
calculate = curry_tail_r_map(checker)
start = time()
xs = calculate(xsin)[::-1]
print('r_map without pattern matching:', time() - start, [xs[0], xs[-1], len(xs)])
...
xs):inline for: [9999900000, 0, 100000]
map: [0, 99998000019999900000, 100000]
r_map without pattern matching: [9999600007999900000899994000029999900000, 0, 100000]
А правильно:inline for: [9999900000, 0, 100000]
map: [9999900000, 0, 100000]
r_map without pattern matching: [9999900000, 0, 100000]
inline for: 0.005000114440917969 [99990000, 0, 10000]
map: 0.004999876022338867 [99990000, 0, 10000]
r_map without pattern matching: 0.5000200271606445 [99990000, 0, 10000]
r_map with pattern matching: 0.9875400066375732 [99990000, 0, 10000]inline for: 0.0650029182434082 [9999900000, 0, 100000]
map: 0.05250191688537598 [9999900000, 0, 100000]
r_map without pattern matching: 50.784531116485596 [9999900000, 0, 100000]
r_map with pattern matching: 85.34341406822205 [9999900000, 0, 100000]Про вашу реализацию на хвостовой рекурсии я умолчу лучше
Т.е. реальный рекурсивный такой (пусть даже хвостовой) пример. Имхо, сравнение будет хотя бы чуть-чуть адекватнее.
inline for: 0.015415668487548828 called: 20000
map: 0.015140533447265625 called: 20000
r_map without pattern matching: 3.7559814453125 called: 20000
r_map with pattern matching: 5.883073806762695 called: 20000
inline for: 0.007587909698486328 called: 10000
map: 0.007678031921386719 called: 10000
r_map without pattern matching: 0.7014162540435791 called: 10000
r_map with pattern matching: 1.3289029598236084 called: 10000
straightforward map: 0.6855792999267578 called: 10000
straightforward map 2: 0.27460575103759766 called: 10000
straightforward map 3: 0.02640247344970703 called: 10000
Не хвостовую, да и не всякую хвостовую в for(да и map, да и в reduce) можно переписать.Любую рекурсию можно развернуть в цикл, уменьшая тем самым накладные на вызов, передачу параметров, обертки scope и т.д. Пример ниже показывает рекурсию на цикле, где параметер «a» постоянный (например лямбда сравнения), «b» и «c» меняются (например бегут по хиерархии сравнивая два дерева). Стоимость «обертки» в таком случае зависит не от количества всех ветвей или того хуже листьев дерева, а от средней глубины его.
def recursive_proc (a, b, c):
stack = []
while 1:
## делаем работу с текущими a, b,c :
...
if next_level:
## push - след. уровень, текущие аргументы в стек :
stack += [[b, c]]
## новые b и c
b, c = ...
continue;
else:
## pop - возврат в пред. уровень :
b, c = stack.pop()
## окончание рекурсии :
if not len(stack):
break
Я как-раз про накладные в вашей реализации обертки
Любую рекурсию можно развернуть в цикл
Создавать же рекурсию на сериях, безконечно создавая и копируя списки — это вообще что-то.
iterate f x == [x, f x, f (f x), ...]" — бесконечный список повторяющихся приложений f от x — думается, что он (уровень) очень и очень на высоте. Хотя это тоже как посмотреть, конструкция ниже например для подсчета суммы через итератор далеко не идеальна (в исполняемом виде):sumList :: [Integer] -> Integer
sumList (x:xs) = x + (sumList xs)
sumList [] = 0
Проблема здесь в том, что ей требуется O(n) от размера передаваемого списка, выделения которой в этом случае можно было бы избежать, например как здесь (как раз вида хвостовой рекурсии):sumList :: [Integer] -> Integer
sumList lst = sumLoop lst 0 where
sumLoop (x:xs) i = sumLoop xs (i+x)
sumLoop [] i = i
Здесь sumLoop в отличии от первого примера использует тот же scope (stack frame), поэтому память «расходуется» sumList гораздо экономней.Traversable. Что же нам теперь, все языки где есть абстракция для обхода коллекции называть функциональными?
Ненормальное функциональное программирование на python