inner methods and recursion

S

Steve Howell

Hi, I have a style/design question relating to recursion and inner
methods.

I wrote some code recently that implements a recursive algorithm that
takes several parameters from the original caller. Once the algorithm
starts running and recursing, those parameters remain the same, so I
define an inner method called "recurse" that essentially curries those
parameters. In particular, the recurse method can get passed to a
callback method that the caller supplies, so that the caller can wrap
the recursive step with their own logic.

The only thing I don't like about the technique that I'm using is that
it seems needlessly repetitive to define mostly the same parameter
list in two different places. The repetition seems mostly harmless,
but it seems like some kind of a smell that I'm overlooking a simpler
way to write the code. I just can't put my finger on what it is.

def indent_lines(lines,
branch_method,
leaf_method,
pass_syntax,
flush_left_syntax,
flush_left_empty_line,
indentation_method,
get_block,
):
def recurse(lines):
return indent_lines(
lines,
branch_method,
leaf_method,
pass_syntax,
flush_left_syntax,
flush_left_empty_line,
indentation_method,
get_block,
)
output = []
while lines:
if lines[0].strip() == '':
lines.pop(0)
output.append('')
else:
prefix, i = get_block(lines, indentation_method)
if i == 1:
line = lines.pop(0)[len(prefix):]
if line == pass_syntax:
pass
elif line.startswith(flush_left_syntax):
output.append(line[len(flush_left_syntax):])
elif line.startswith(flush_left_empty_line):
output.append('')
else:
output.append(prefix + leaf_method(line))
else:
block = lines[:i]
lines = lines[i:]
output += branch_method(prefix, block, recurse)
return output

Does anybody have any inspiration here? I vaguely recall a discussion
some time back about having some kind of @recursive decorator, but I
can't seem to find the thread.
 
G

Gabriel Genellina

Hi, I have a style/design question relating to recursion and inner
methods.

I wrote some code recently that implements a recursive algorithm that
takes several parameters from the original caller. Once the algorithm
starts running and recursing, those parameters remain the same, so I
define an inner method called "recurse" that essentially curries those
parameters. In particular, the recurse method can get passed to a
callback method that the caller supplies, so that the caller can wrap
the recursive step with their own logic.

Python already have lexical scoping, you can take advantage of it. On any
non-prehistoric version of Python you may write:


def indent_lines(lines,
branch_method,
leaf_method,
pass_syntax,
flush_left_syntax,
flush_left_empty_line,
indentation_method,
get_block,
):

def _indent_lines(lines):
output = []
while lines:
# ... the real work ...
# recursive call:
output += branch_method(prefix, block, _indent_lines)
return output

return _indent_lines(lines)

The real work happens inside _indent_lines, and it has access to the outer
indent_lines scope, where all remaining parameters are defined.
The only thing I don't like about the technique that I'm using is that
it seems needlessly repetitive to define mostly the same parameter
list in two different places. The repetition seems mostly harmless,
but it seems like some kind of a smell that I'm overlooking a simpler
way to write the code. I just can't put my finger on what it is.

Is the above technique what you were looking for?
Does anybody have any inspiration here? I vaguely recall a discussion
some time back about having some kind of @recursive decorator, but I
can't seem to find the thread.

The thread I remember was about making "true" recursive calls (normal
recursive calls at global or method scope are not truly recursive: they
actually perform a name lookup, which may or may not yield the original
function). In the above case, that doesn't happen, the recursive call
resolves the _indent_lines name directly using a cell "pointing" into its
container local scope.
 
S

Steve Howell

Hi, I have a style/design question relating to recursion and inner
methods.
I wrote some code recently that implements a recursive algorithm that
takes several parameters from the original caller.  Once the algorithm
starts running and recursing, those parameters remain the same, so I
define an inner method called "recurse" that essentially curries those
parameters.  In particular, the recurse method can get passed to a
callback method that the caller supplies, so that the caller can wrap
the recursive step with their own logic.

Python already have lexical scoping, you can take advantage of it. On any  
non-prehistoric version of Python you may write:

def indent_lines(lines,
             branch_method,
             leaf_method,
             pass_syntax,
             flush_left_syntax,
             flush_left_empty_line,
             indentation_method,
             get_block,
             ):

     def _indent_lines(lines):
       output = []
       while lines:
         # ... the real work ...
         # recursive call:
         output += branch_method(prefix, block, _indent_lines)
       return output

     return _indent_lines(lines)

The real work happens inside _indent_lines, and it has access to the outer  
indent_lines scope, where all remaining parameters are defined.
The only thing I don't like about the technique that I'm using is that
it seems needlessly repetitive to define mostly the same parameter
list in two different places.  The repetition seems mostly harmless,
but it seems like some kind of a smell that I'm overlooking a simpler
way to write the code.  I just can't put my finger on what it is.

Is the above technique what you were looking for?

That was exactly what I was looking for. I just tried it out, and it
works perfectly. Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top