Re: Recursive calls and stack

2007-02-15 Thread Neil Cerutti
On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Wed, 14 Feb 2007 10:41:53 -0300, Neil Cerutti [EMAIL PROTECTED]  
 escribió:
 So the effect is that mutual recursion isn't actually any
 harder.

 But some kind of language support is required in this case. At
 least I  don't know how to handle mutual recursion (apart from
 inlining one  function inside the other...). But I'm certainly
 not a program  transformation guru (neither a novice!) so I
 would not be surprised if  someone says it can be done...

What happens (using the model of an imaginary virtual machine,
perhaps like the Python interpreter) is the following.

A normal function call pushes a call-frame onto a stack. The
call-frame contains information necessary for returning from the
function, and usually a place to store its local variables and
parameters.

A function called in tail position simply overwrites the
current call-frame with the new one instead of pushing it onto
the stack.

-- 
Neil Cerutti
The church will host an evening of fine dining, superb entertainment, and
gracious hostility. --Church Bulletin Blooper
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-15 Thread Gabriel Genellina
En Thu, 15 Feb 2007 13:37:19 -0300, Neil Cerutti [EMAIL PROTECTED]  
escribió:

 On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Wed, 14 Feb 2007 10:41:53 -0300, Neil Cerutti [EMAIL PROTECTED]
 escribió:
 So the effect is that mutual recursion isn't actually any
 harder.

 But some kind of language support is required in this case. At
 least I  don't know how to handle mutual recursion (apart from
 inlining one  function inside the other...). But I'm certainly
 not a program  transformation guru (neither a novice!) so I
 would not be surprised if  someone says it can be done...

 What happens (using the model of an imaginary virtual machine,
 perhaps like the Python interpreter) is the following.

 A normal function call pushes a call-frame onto a stack. The
 call-frame contains information necessary for returning from the
 function, and usually a place to store its local variables and
 parameters.

 A function called in tail position simply overwrites the
 current call-frame with the new one instead of pushing it onto
 the stack.

This is the kind of language support menctioned. For tail recursion you  
don't require that support.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-15 Thread Neil Cerutti
On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Thu, 15 Feb 2007 13:37:19 -0300, Neil Cerutti [EMAIL PROTECTED]  
 escribió:

 On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Wed, 14 Feb 2007 10:41:53 -0300, Neil Cerutti [EMAIL PROTECTED]
 escribió:
 So the effect is that mutual recursion isn't actually any
 harder.

 But some kind of language support is required in this case. At
 least I  don't know how to handle mutual recursion (apart from
 inlining one  function inside the other...). But I'm certainly
 not a program  transformation guru (neither a novice!) so I
 would not be surprised if  someone says it can be done...

 What happens (using the model of an imaginary virtual machine,
 perhaps like the Python interpreter) is the following.

 A normal function call pushes a call-frame onto a stack. The
 call-frame contains information necessary for returning from the
 function, and usually a place to store its local variables and
 parameters.

 A function called in tail position simply overwrites the
 current call-frame with the new one instead of pushing it onto
 the stack.

 This is the kind of language support menctioned. For tail
 recursion you  don't require that support.

I'm not sure what you mean. The above support is enough for tail
recursion, mutual recursion, and any other tail call to be
optimized.

-- 
Neil Cerutti
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-15 Thread Gabriel Genellina
En Thu, 15 Feb 2007 16:35:25 -0300, Neil Cerutti [EMAIL PROTECTED]  
escribió:

 On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Thu, 15 Feb 2007 13:37:19 -0300, Neil Cerutti [EMAIL PROTECTED]
 escribió:

 On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Wed, 14 Feb 2007 10:41:53 -0300, Neil Cerutti [EMAIL PROTECTED]
 escribió:
 So the effect is that mutual recursion isn't actually any
 harder.

 But some kind of language support is required in this case. At
 least I  don't know how to handle mutual recursion (apart from
 inlining one  function inside the other...). But I'm certainly
 not a program  transformation guru (neither a novice!) so I
 would not be surprised if  someone says it can be done...

 What happens (using the model of an imaginary virtual machine,
 perhaps like the Python interpreter) is the following.

 A normal function call pushes a call-frame onto a stack. The
 call-frame contains information necessary for returning from the
 function, and usually a place to store its local variables and
 parameters.

 A function called in tail position simply overwrites the
 current call-frame with the new one instead of pushing it onto
 the stack.

 This is the kind of language support menctioned. For tail
 recursion you  don't require that support.

 I'm not sure what you mean. The above support is enough for tail
 recursion, mutual recursion, and any other tail call to be
 optimized.

I only want to say that tail *recursion* can be eliminated trivially  
transforming the code into a while loop, and that can be done by the  
programmer, and doesn't require compiler support. Head *recursion* can be  
eliminated too by using some storage as temporary stack, and that doesn't  
require external support either. Mutual recursion (and generic tail call  
elimination) require some sort of external support: one can't eliminate  
the call just by transforming the program.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-15 Thread Neil Cerutti
On 2007-02-15, Gabriel Genellina [EMAIL PROTECTED] wrote:
 I'm not sure what you mean. The above support is enough for
 tail recursion, mutual recursion, and any other tail call to
 be optimized.

 I only want to say that tail *recursion* can be eliminated
 trivially  transforming the code into a while loop, and that
 can be done by the  programmer, and doesn't require compiler
 support. Head *recursion* can be  eliminated too by using some
 storage as temporary stack, and that doesn't  require external
 support either. Mutual recursion (and generic tail call
 elimination) require some sort of external support: one can't
 eliminate  the call just by transforming the program.

Ah, I see now. Had my blinders on.

-- 
Neil Cerutti
Low Self-Esteem Support Group will meet Thursday at 7 to 8:30 p.m. Please use
the back door. --Church Bulletin Blooper
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread Gabriel Genellina
En Wed, 14 Feb 2007 04:23:46 -0300, [EMAIL PROTECTED]  
[EMAIL PROTECTED] escribió:

 I am OK with calls being stacked, but I wondering will the local
 variables be stacked given that return statement is followed by the
 function call?

 def test():
   x = 22
   y = 33
   z = x+y
   return anotherFunction(z)

 In this function will all the local variables (x,y,z) be pushed into
 the stack before calling anotherFunction(z) or Python will find out
 that the locals are no longer needed as anotherFunction(z) is just
 returned?

Not exactly like pushed into the stack, but there exists a frame object,  
and it contains references to its local variables, and will be alive until  
anotherFunction returns. From inside anotherFunction you can even inspect  
those variables:

py def test():
...   x = 22
...   y = 33
...   z = x+y
...   return anotherFunction(z)
...
py def anotherFunction(z):
...   print previous frame:, sys._getframe(1).f_locals
...
py test()
previous frame: {'y': 33, 'x': 22, 'z': 55}

So x,y,z will still be there until anotherFunction actually returns to  
test, and the frame object is disposed. For a highly recursive function,  
that's bad news. For debugging normal programs, that's good news; the  
cgitb module, by example, is able to show the values for local variables  
in all previous frames when an exception is raised.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread [EMAIL PROTECTED]
On Feb 14, 11:09 am, [EMAIL PROTECTED]
[EMAIL PROTECTED] wrote:
 Hi,
  I have a program which literately finds the object that overlapping a
 point. The horizontal and vertical search are called recursively from
 inside each other.
  Is this way of implementation fill thestackspace with the local
 variables inside eachcall. If this is not good, is there a better way
 to implement? Orpythonitself will understand that the calls happen
 in the last line, so local variables need not be pushed into thestack?

 def find_point(pt):
 return _hor_search(pt, random_obj)

 def _hor_search(pt, obj):
 ...
 object = ...
 ...
 if object meets some condition:
 return object
 else:
 return _ver_search(pt, object)

 def _ver_search(pt, obj):
 ...
 object = ...
 ...
 if object meets some condition:
 return object
 else:
 return _hor_search(pt, object)

 -
 Suresh

I found a simpler solution: get rid of recursive calls; using while
loops.

-
Suresh

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread Terry Reedy

[EMAIL PROTECTED] [EMAIL PROTECTED] wrote in message 
news:[EMAIL PROTECTED]
I am OK with calls being stacked, but I wondering will the local
variables be stacked given that return statement is followed by the
function call?

def test():
  x = 22
  y = 33
  z = x+y
  return anotherFunction(z)

In this function will all the local variables (x,y,z) be pushed into
the stack before calling anotherFunction(z) or Python will find out
that the locals are no longer needed as anotherFunction(z) is just
returned?
=
To add to Gabriel's answer:

Questions of this sort are implementation specific.  CPython will allocate 
the objects on the heap.  But I believe at present something will go on the 
C stack with each function call.  I suspect that the C array that typically 
implements the local namespace is included but don't specifically know. 
The local names are deleted, and the associated heap objects released if 
that make the reference count 0, as part of the return process.  No 
optimization of the sort you indicate is done.  Indeed, the heap objects 
could have other references, and the namespace array is fixed size, so I am 
not sure there is anything that could, in general, be done.  In any case, 
Python never deletes without at least implicit instruction to do so.

The maximun recursion depth CPython will attempt is governed by an internal 
variable that you can get and set to adjust to your problem and hardware:

 sys.getrecursionlimit()
1000
 sys.setrecursionlimit(500)
 sys.getrecursionlimit()
500

Terry Jan Reedy




-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread Neil Cerutti
On 2007-02-14, Gabriel Genellina [EMAIL PROTECTED] wrote:
 En Wed, 14 Feb 2007 03:09:37 -0300, [EMAIL PROTECTED]  
[EMAIL PROTECTED] escribió:
  Is this way of implementation fill the stack space with the
  local variables inside each call. If this is not good, is
  there a better way to implement? Or python itself will
  understand that the calls happen in the last line, so local
  variables need not be pushed into the stack?

 I'm afraid not, the calls will be stacked until some object is
 found. Python does not do tail recursion optimization (at
 least, I'm not aware  of that).

To be just a little pedantic, it's tail call optimization. Any
tail call can be optimized, not just recursive ones.

 But even if it could do that, in this case you have recursive
 calls between two functions, and that's a bit harder.

So the effect is that mutual recursion isn't actually any harder.

Moreover, if his functions calls really are tail-calls, then
translating them by hand into iteration might be fairly easy.

A simple, silly example:

def sum(seq):
  if len(seq) == 0:
return 0
  else:
return seq[0] + sum(seq[1:])

Above, sum is not a tail call, since the + operation must be
defered until after the call to sum returns.

Below, sum is a tail call.

def sum(seq, accum=0):
  if len(seq) == 0:
return accum
  else:
return sum(seq[1:], accum+s[0])

Since no state must be retained by sum when calling sum, it's a
tail call. The last version translates more or less directly into
a dumb while loop.

I don't believe Python does tail call optimization; at least it
isn't document that it does it.

-- 
Neil Cerutti
The audience is asked to remain seated until the end of the recession.
--Church Bulletin Blooper
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread Gabriel Genellina
En Wed, 14 Feb 2007 10:41:53 -0300, Neil Cerutti [EMAIL PROTECTED]  
escribió:

 On 2007-02-14, Gabriel Genellina [EMAIL PROTECTED] wrote:
 Python does not do tail recursion optimization (at
 least, I'm not aware  of that).

 To be just a little pedantic, it's tail call optimization. Any
 tail call can be optimized, not just recursive ones.

Maybe, but I didn't invent the term:
http://computing-dictionary.thefreedictionary.com/tail%20recursion%20optimisation
It's true that tail recursion is a special case of tail call - but it's  
just the case that can be managed by hand, no special support on the  
language -trampoline or whatever- is required (just a loop, GOTO 1).

 But even if it could do that, in this case you have recursive
 calls between two functions, and that's a bit harder.

 So the effect is that mutual recursion isn't actually any harder.

But some kind of language support is required in this case. At least I  
don't know how to handle mutual recursion (apart from inlining one  
function inside the other...). But I'm certainly not a program  
transformation guru (neither a novice!) so I would not be surprised if  
someone says it can be done...

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-14 Thread Szabolcs Nagy

[EMAIL PROTECTED] wrote:
 Hi,
  I have a program which literately finds the object that overlapping a
 point. The horizontal and vertical search are called recursively from
 inside each other.
 ...

in case you ever need deeply nested recursion:
one solution is to use the already mentioned sys.setrecursionlimit(n)
another is to use your own stack

dummy example:

def fact_recursive(n):
if n0:
return fact_recursive(n-1)*n
else:
return 1

def fact_iterative(n):
stack = []
while n  0:
stack.append(n)
n -= 1
ret = 1
while stack:
ret *= stack.pop()
return ret

actually you can always rewrite recursion with a stack and iterations

note that if you use version = 2.4, then collections.deque is faster
for stack (and especially for queue) data structure than list.

-- 
http://mail.python.org/mailman/listinfo/python-list


Recursive calls and stack

2007-02-13 Thread [EMAIL PROTECTED]
Hi,
 I have a program which literately finds the object that overlapping a
point. The horizontal and vertical search are called recursively from
inside each other.
 Is this way of implementation fill the stack space with the local
variables inside each call. If this is not good, is there a better way
to implement? Or python itself will understand that the calls happen
in the last line, so local variables need not be pushed into the
stack?

def find_point(pt):
return _hor_search(pt, random_obj)

def _hor_search(pt, obj):
...
object = ...
...
if object meets some condition:
return object
else:
return _ver_search(pt, object)

def _ver_search(pt, obj):
...
object = ...
...
if object meets some condition:
return object
else:
return _hor_search(pt, object)


-
Suresh

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-13 Thread Gabriel Genellina
En Wed, 14 Feb 2007 03:09:37 -0300, [EMAIL PROTECTED]  
[EMAIL PROTECTED] escribió:

 Hi,
  I have a program which literately finds the object that overlapping a
 point. The horizontal and vertical search are called recursively from
 inside each other.
  Is this way of implementation fill the stack space with the local
 variables inside each call. If this is not good, is there a better way
 to implement? Or python itself will understand that the calls happen
 in the last line, so local variables need not be pushed into the
 stack?

I'm afraid not, the calls will be stacked until some object is found.
Python does not do tail recursion optimization (at least, I'm not aware  
of that). But even if it could do that, in this case you have recursive  
calls between two functions, and that's a bit harder.

Going back to your original problem, maybe you can use some known  
algorithms from computational geometry; start with  
http://www.faqs.org/faqs/graphics/algorithms-faq/

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Recursive calls and stack

2007-02-13 Thread [EMAIL PROTECTED]
On Feb 14, 11:45 am, Gabriel Genellina [EMAIL PROTECTED]
wrote:
 En Wed, 14 Feb 2007 03:09:37 -0300, [EMAIL PROTECTED]
 [EMAIL PROTECTED] escribió:

  Hi,
   I have a program which literately finds the object that overlapping a
  point. The horizontal and vertical search are called recursively from
  inside each other.
   Is this way of implementation fill the stack space with the local
  variables inside each call. If this is not good, is there a better way
  to implement? Or python itself will understand that the calls happen
  in the last line, so local variables need not be pushed into the
  stack?

 I'm afraid not, the calls will be stacked until some object is found.
 Python does not do tail recursion optimization (at least, I'm not aware
 of that). But even if it could do that, in this case you have recursive
 calls between two functions, and that's a bit harder.

 Going back to your original problem, maybe you can use some known
 algorithms from computational geometry; start with  
 http://www.faqs.org/faqs/graphics/algorithms-faq/

 --
 Gabriel Genellina

Thanks Gabriel for the response.

I am OK with calls being stacked, but I wondering will the local
variables be stacked given that return statement is followed by the
function call?

def test():
  x = 22
  y = 33
  z = x+y
  return anotherFunction(z)

In this function will all the local variables (x,y,z) be pushed into
the stack before calling anotherFunction(z) or Python will find out
that the locals are no longer needed as anotherFunction(z) is just
returned?

-
Suresh

-- 
http://mail.python.org/mailman/listinfo/python-list