Limitless and recursion-free recursion limits!

401 views

Published on

Bangbangcon 2015

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
401
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
1
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Limitless and recursion-free recursion limits!

  1. 1. Limitless and recursion-free recursion limits!
  2. 2. >>> def factorial(n): ... if n == 1: ... return 1 ... else: ... return n * factorial(n - 1)
  3. 3. >>> factorial(10) 3628800
  4. 4. >>> factorial(500) 1220136825991110068701238785423046926253574342803192842192413588385845373153881 9976054964475022032818630136164771482035841633787220781772004807852051593292854 7790757193933060377296085908627042917454788242491272634430567017327076946106280 2310452644218878789465754777149863494367781037644274033827365397471386477878495 4384895955375379904232410612713269843277457155463099772027810145610811883737095 3101635632443298702956389662891165897476957208792692887128178007026517450776841 0719624390394322536422605234945850129918571501248706961568141625359056693423813 0088562492468915641267756544818865065938479517753608940057452389403357984763639 4490531306232374906644504882466507594673586207463792518420045936969298102226397 1952597190945217823331756934581508552332820762820023402626907898342451712006207 7146409794561161276291459512372299133401695523638509428855920187274337951730145 8635757082835578015873543276888868012039988238470215146760544540766353598417443 0480128938313896881639487469658817504506926365338175055478128640000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000L
  5. 5. >>> factorial(999) 40238726007709377354370243392300398571937486421071463254379991042993851239862902059204420848696940480047998 86101971960586316668729948085589013238296699445909974245040870737599188236277271887325197795059509952761208 74975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513 18532395846307555740911426241747434934755342864657661166779739666882029120737914385371958824980812686783837 45597317461360853795345242215865932019280908782973084313928444032812315586110369768013573042161687476096758 71348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691 39828126481021309276124489635992870511496497541990934222156683257208082133318611681155361583654698404670897 56029009505376164758477284218896796462449451607653534081989013854424879849599533191017233555566021394503997 36280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257 22386554146106289218796022383897147608850627686296714667469756291123408243920816015378088989396451826324367 16167621791689097799119037540312746222899880051954444142820121873617459926429565817466283029555702990243241 53181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458 32716822645806652676995865268227280707578139185817888965220816434834482599326604336766017699961283186078838 61502794659551311565520360939881806121385586003014356945272242063446317974605946825731037900840244324384656 57245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387 53823048386568897646192738381490014076731044664025989949022222176590433990188601856652648506179970235619389 70178600408118897299183110211712298459016419210688843871218556461249607987229085192968193723886426148396573 82291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483 07764456909907315243327828826986460278986432113908350621709500259738986355427719674282224875758676575234422 02075736305694988250879689281627538488633969099598262809561214509948717012445164612603790293091208890869420 28510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524 23056085590370062427124341690900415369010593398383577793941097002775347200000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L
  6. 6. >>> factorial(1000)
  7. 7. File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial RuntimeError: maximum recursion depth exceeded
  8. 8. :(
  9. 9. Recursion limit
  10. 10. >>> import sys >>> sys.setrecursionlimit(10**8)
  11. 11. >>> factorial(1000) 40238726007709377354370243392300398571937486421071463254379991042993851239862902059204420848696940480047998 86101971960586316668729948085589013238296699445909974245040870737599188236277271887325197795059509952761208 74975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513 18532395846307555740911426241747434934755342864657661166779739666882029120737914385371958824980812686783837 45597317461360853795345242215865932019280908782973084313928444032812315586110369768013573042161687476096758 71348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691 39828126481021309276124489635992870511496497541990934222156683257208082133318611681155361583654698404670897 56029009505376164758477284218896796462449451607653534081989013854424879849599533191017233555566021394503997 36280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257 22386554146106289218796022383897147608850627686296714667469756291123408243920816015378088989396451826324367 16167621791689097799119037540312746222899880051954444142820121873617459926429565817466283029555702990243241 53181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458 32716822645806652676995865268227280707578139185817888965220816434834482599326604336766017699961283186078838 61502794659551311565520360939881806121385586003014356945272242063446317974605946825731037900840244324384656 57245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387 53823048386568897646192738381490014076731044664025989949022222176590433990188601856652648506179970235619389 70178600408118897299183110211712298459016419210688843871218556461249607987229085192968193723886426148396573 82291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483 07764456909907315243327828826986460278986432113908350621709500259738986355427719674282224875758676575234422 02075736305694988250879689281627538488633969099598262809561214509948717012445164612603790293091208890869420 28510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524 23056085590370062427124341690900415369010593398383577793941097002775347200000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 L
  12. 12. >>> factorial(1000000)
  13. 13. >>> factorial(1000000) Segmentation fault: 11
  14. 14. :( :( :(
  15. 15. :D
  16. 16. :D
  17. 17. >>> def factorial(n): ... if n == 1: ... return 1 ... else: ... return n * factorial(n - 1)
  18. 18. if (tstate->recursion_depth > recursion_limit) { --tstate->recursion_depth; PyErr_Format(PyExc_RuntimeError, "maximum recursion depth exceeded%s", where); return -1; }
  19. 19. ... c ------------- a | factorial | l ------------- l | factorial | ------------- s | factorial | t ------------- a | factorial | c ------------- k | REPL | <-- this one counts! -------------
  20. 20. :D
  21. 21. Tail Call Optimization
  22. 22. c ------------- a | factorial | (1) >>> def factorial(n): l ------------- ... if n == 1: l | factorial | (2) ... return 1 ------------- ... else: s | factorial | (3) ... return n * factorial(n - 1) t ------------- a | factorial | (4) c ------------- k | factorial | (5) ------------- | REPL | -------------
  23. 23. def factorial(n, accumulator): if n <= 1: return accumulator else: return factorial(n-1, accumulator * n)
  24. 24. >>> factorial(1000)
  25. 25. File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial File "<stdin>", line 5, in factorial RuntimeError: maximum recursion depth exceeded
  26. 26. OR DOES IT. with Liuda Nikolaeva and Paul Tagliamonte
  27. 27. def fact(n, accumulator): 10 if n <= 1: return accumulator else: n = n - 1; accumulator = accumulator * n GOTO 10 # return fact(n-1, accum*n)
  28. 28. or is there
  29. 29. >>> import dis >>> dis.dis(factorial) 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 1 (<=) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_FAST 1 (accumulator) 15 RETURN_VALUE 5 >> 16 LOAD_GLOBAL 0 (factorial) 19 LOAD_FAST 0 (n) 22 LOAD_CONST 1 (1) 25 BINARY_SUBTRACT 26 LOAD_FAST 1 (accumulator) 29 LOAD_FAST 0 (n) 32 BINARY_MULTIPLY 33 CALL_FUNCTION 2 36 RETURN_VALUE 37 LOAD_CONST 0 (None) 40 RETURN_VALUE
  30. 30. >>> import dis >>> dis.dis(factorial) 2 0 LOAD_FAST 0 (n) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 1 (<=) 9 POP_JUMP_IF_FALSE 16 3 12 LOAD_FAST 1 (accumulator) 15 RETURN_VALUE 5 >> 16 NOP 19 LOAD_FAST 0 (n) 22 LOAD_CONST 1 (1) 25 BINARY_SUBTRACT 26 LOAD_FAST 1 (accumulator) 29 LOAD_FAST 0 (n) 32 BINARY_MULTIPLY 33 JUMP_ABSOLUTE 0 36 RETURN_VALUE 37 LOAD_CONST 0 (None) 40 RETURN_VALUE
  31. 31. >>> def hi(): ... print("hi!") ... >>> def nope(): ... print("haha, nope!") ... >>> hi.__code__ = nope.__code__ >>> hi() haha, nope!
  32. 32. def tail_recurse(fn): new_bytecode = [] code_obj = fn.__code__ for byte, arg in consume(code_obj.co_code): name = opcode.opname[byte] if name == "LOAD_GLOBAL" and code_obj.co_names[arg] == fn.__name__: pass elif name == "CALL_FUNCTION": for i in range(arg): new_bytecode.append(opmap["STORE_FAST"]) new_bytecode += split(arg - i - 1) new_bytecode.append(opmap["JUMP_ABSOLUTE"]) new_bytecode += split(0) # jump to beginning of bytecode else: new_bytecode.append(byte) if arg is not None: new_bytecode += split(arg) return "".join([chr(b) for b in new_bytecode])
  33. 33. $ python factorial_tco.py 1000 40238726007709377354370243392300398571937486421071463254379991042993851239862902059204420848696940480047998 86101971960586316668729948085589013238296699445909974245040870737599188236277271887325197795059509952761208 74975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513 18532395846307555740911426241747434934755342864657661166779739666882029120737914385371958824980812686783837 45597317461360853795345242215865932019280908782973084313928444032812315586110369768013573042161687476096758 71348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691 39828126481021309276124489635992870511496497541990934222156683257208082133318611681155361583654698404670897 56029009505376164758477284218896796462449451607653534081989013854424879849599533191017233555566021394503997 36280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257 22386554146106289218796022383897147608850627686296714667469756291123408243920816015378088989396451826324367 16167621791689097799119037540312746222899880051954444142820121873617459926429565817466283029555702990243241 53181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458 32716822645806652676995865268227280707578139185817888965220816434834482599326604336766017699961283186078838 61502794659551311565520360939881806121385586003014356945272242063446317974605946825731037900840244324384656 57245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387 53823048386568897646192738381490014076731044664025989949022222176590433990188601856652648506179970235619389 70178600408118897299183110211712298459016419210688843871218556461249607987229085192968193723886426148396573 82291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483 07764456909907315243327828826986460278986432113908350621709500259738986355427719674282224875758676575234422 02075736305694988250879689281627538488633969099598262809561214509948717012445164612603790293091208890869420 28510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524 23056085590370062427124341690900415369010593398383577793941097002775347200000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 L
  34. 34. $ python factorial_tco.py 1000000 # ONE MILLION
  35. 35. :D
  36. 36. >>> sys.setrecursionlimit(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError >>> sys.setrecursionlimit(5) RuntimeError >>> sys.setrecursionlimit(10) RuntimeError >>> sys.setrecursionlimit(100) RuntimeError
  37. 37. >>> sys.setrecursionlimit(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError >>> sys.setrecursionlimit(5) RuntimeError >>> sys.setrecursionlimit(10) RuntimeError >>> sys.setrecursionlimit(100) RuntimeError >>> a = 1 RuntimeError >>> 7 RuntimeError
  38. 38. >>> ^D Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x103b9e6e0> ignored Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x103ba25f0> ignored
  39. 39. !! :D

×