Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Limitless and
recursion-free
recursion limits!
>>> def factorial(n):
... if n == 1:
... return 1
... else:
... return n * factorial(n - 1)
>>> factorial(10)
3628800
>>> factorial(500)
1220136825991110068701238785423046926253574342803192842192413588385845373153881
99760549644750220328186...
>>> factorial(999)
4023872600770937735437024339230039857193748642107146325437999104299385123986290205920442084869694048004...
>>> factorial(1000)
File "<stdin>", line 5, in factorial
File "<stdin>", line 5, in factorial
File "<stdin>", line 5, in factorial
File "<stdi...
:(
Recursion limit
>>> import sys
>>> sys.setrecursionlimit(10**8)
>>> factorial(1000)
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800...
>>> factorial(1000000)
>>> factorial(1000000)
Segmentation fault: 11
:( :( :(
:D
:D
>>> def factorial(n):
... if n == 1:
... return 1
... else:
... return n * factorial(n - 1)
if (tstate->recursion_depth > recursion_limit) {
--tstate->recursion_depth;
PyErr_Format(PyExc_RuntimeError,
"maximum recu...
...
c -------------
a | factorial |
l -------------
l | factorial |
-------------
s | factorial |
t -------------
a | fact...
:D
Tail Call Optimization
c -------------
a | factorial | (1) >>> def factorial(n):
l ------------- ... if n == 1:
l | factorial | (2) ... return 1
...
def factorial(n, accumulator):
if n <= 1:
return accumulator
else:
return factorial(n-1, accumulator * n)
>>> factorial(1000)
File "<stdin>", line 5, in factorial
File "<stdin>", line 5, in factorial
File "<stdin>", line 5, in factorial
File "<stdi...
OR DOES IT.
with Liuda Nikolaeva and Paul Tagliamonte
def fact(n, accumulator):
10
if n <= 1:
return accumulator
else:
n = n - 1;
accumulator = accumulator * n
GOTO 10
# return...
or is there
>>> 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 ...
>>> 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 ...
>>> def hi():
... print("hi!")
...
>>> def nope():
... print("haha, nope!")
...
>>> hi.__code__ = nope.__code__
>>> hi()
h...
def tail_recurse(fn):
new_bytecode = []
code_obj = fn.__code__
for byte, arg in consume(code_obj.co_code):
name = opcode.o...
$ python factorial_tco.py 1000
4023872600770937735437024339230039857193748642107146325437999104299385123986290205920442084...
$ python factorial_tco.py 1000000 # ONE MILLION
:D
>>> sys.setrecursionlimit(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError
>>> sys.s...
>>> sys.setrecursionlimit(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError
>>> sys.s...
>>> ^D
Exception RuntimeError: 'maximum recursion depth exceeded'
in <function _remove at 0x103b9e6e0> ignored
Exception R...
!! :D
Limitless and recursion-free recursion limits!
Upcoming SlideShare
Loading in …5
×

Limitless and recursion-free recursion limits!

788 views

Published on

Bangbangcon 2015

Published in: Technology
  • Be the first to comment

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

×