You are viewing a plain text version of this content. The canonical link for it is here.
Posted to embperl@perl.apache.org by Nate Smith <na...@thebackrow.net> on 2002/07/19 21:47:31 UTC

Deep Recursion

I am not having much luck getting a recursive function to work as it
should.  I have written it in standard perl and it works as I intend it
to, it is reading records from a database table that looks like this:

| id          | int(11)    
| child_of    | int(11) 
| item_number | int(11) 
| data        | blob    

this table holds information for a to-do list, where an item can be a
top level item (child_of == 0) or a child (sub-item) of any other item
in the list, so I end up with a structure like this from running the
code below:

[fileman:~]> ./recur.pl
1 : Medivision
   \==> 2 : Call Pete
3 : Laser
      \==> 6 : Upgrade Laser
      \==> 7 : Automate Laser
4 : PDM
   \==> 15 : IT Documentation
   \==> 14 : Cleanup PDM
   \==> 13 : Install PDM
   \==> 12 : TIQD
5 : IT
   \==> 16 : Automate IT Stuff
      \==> 18 : Automate This
      \==> 19 : Automate That
   \==> 17 : Backup IT STuff
      \==> 20 : Backup That
      \==> 21 : Backup This

So after reimplementing this in embperl, the problems I have are in
getting the recursive function to work.  I've read the man page, 
online docs, and searched the mailing list archives, and they all seem
to indicate that the *opposite* of what I'm observing should be
happening.  (BTW, i'm using embperl 1.3.4)

I call it initially with two arguments, both zero.

&printTree(0,0);

sub printTree {

 my ($parent, $depth) = @_;
 my $sth = $dbh->prepare( "select id, data, child_of from to_do where child_of = '$parent'" );
    $sth->execute();

 while( my ($child, $data, $child_of) = $sth->fetchrow_array() ) {
   my $tmp = ($depth > 0) ? "\\==> " : "";
   print "", "   " x $depth, $tmp, "$child : $data \n";
   my $sth = $dbh->prepare( "select count(*) from to_do where child_of = '$child'" );
      $sth->execute();
   my ($children) = $sth->fetchrow_array();
   if ($children > 0) {
     my $newDepth = $depth + 1;
     &printTree($child, $newDepth);
   } else {
   }
 }
}


Despite the documentation to the contrary, I can't get a recursive
function to work with embperl's Execute():



 <table border=1>
    [- 
      #Execute ({sub => 'printTree', param => ['0', '0'] });
      printTree(0, 0); 
    -]
 </table>

[$ sub printTree $]
  [-
   ($parent, $depth) = @_;
   print OUT "In PrintTree with depth = $depth, parent = $parent\n";
   $sth = $dbh->prepare( "select id, data from to_do where child_of = '$parent'" ); 
   $sth->execute();
  -]
  [$ while ($child, $data) = $sth->fetchrow_array() $]
   <tr> <td> 
     [+ $child +] :: [+ $data +] 
   </td></tr>
   [-  # this is line 43
     $sth = $dbh->prepare( "select count(*) from to_do where child_of = '$child'" );
     $sth->execute();
     my ($children) = $sth->fetchrow_array();
     if ($children > 0) {
        my $newDepth = $depth + 1;
        #Execute ({ sub => 'printTree', param => [$child, $newDepth] });
        printTree($child, $newDepth);
     }
   -]
  [$ endwhile $]
[$ endsub $]


The calls to printTree using Execute are commented out since when I use
those it returns an invalid response and my access_log recieves these:

Warning in Perl code: Deep recursion on subroutine "HTML::Embperl::Execute" at line 49
Warning in Perl code: Deep recursion on subroutine "HTML::Embperl::CleanCallExecuteReq" in block starting at line 1
Warning in Perl code: Deep recursion on anonymous subroutine at line 43
(line 43 is marked above)


Any clue why this doesn't work?

Thanks in advance,

Nate Smith

---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


Re: Deep Recursion

Posted by Nate Smith <na...@thebackrow.net>.
Ok, for anyone following this thread, I got the recursive function to
work, I will paste the source here.  I could not declare it as an
embperl sub, I had to declare it as a normal perl sub within an
embperl block in the same file as I am using it.  I tried about every
other iteration without success.  Thanks to Gerald for your help, 
if you can think of a better way to do this  (namely one that lets me
write the html without extra \'s and perl print OUT statements) I'd
love to hear it.  Thanks again for making the tool that takes the 
drudgery out of making forms and HTML.

The only other real option would have been to jump to 2.0,
and I don't particularly want to do that before migrating to apache 2.  

Anyway, here be the code:

[- 
   $dsn = 'your:info:goes:here';
   $user = 'user';
   $pass = 'pass';
   %attr = ( PrintError => 1, RaiseError => 0 );
   $dbh = DBI->connect ( $dsn, $user, $pass, \%attr );

sub printTree {

 my ($parent, $depth) = (0, 0);
    ($parent, $depth) = @_ if (defined (@_));

 # might want to add some sanity checks here on the input..

 my $sth = $dbh->prepare( "select id, data, child_of, item_number from to_do where child_of = '$parent' order by item_number" );
    $sth->execute();

 while( my ($child, $data, $child_of, $item_number) = $sth->fetchrow_array() ) {

   print OUT "\<tr>\<td>";
   print OUT "-- " x $depth;
   print OUT "$item_number : $data \</tr>\</td>";

   my $sth = $dbh->prepare( "select count(*) from to_do where child_of = '$child'" );
      $sth->execute();
   my ($children) = $sth->fetchrow_array();

   printTree($child, $depth+1) if $children;
 }

}

-]

  <table border="0">
   [- printTree -] 
  </table>

__END_EMBPERL__

That is to accompany a db table such with at least these columns:

+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | int(11)     |      | PRI | NULL    | auto_increment |
| child_of    | int(11)     |      |     | 0       |                |
| item_number | int(11)     | YES  |     | NULL    |                |
| data        | blob        |      |     |         |                |
+-------------+-------------+------+-----+---------+----------------+



---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


Re: Deep Recursion

Posted by Gerald Richter <ri...@ecos.de>.
>
> When I do this, it appears as if it is not even processing the [* *]
> sections.

Embperl subs must be defined before they are used in 1.3.4 (this isn't
necessary in 2.0 anymore), which is not the case in your example. When you
move the sub before the call of the sub it should work.

>  Does it matter that I'm using EmbperlObject?

No

>From your other mail:

> (namely one that lets me
> write the html without extra \'s and perl print OUT statements)

Looks like you should set optRawInput in EMBPERL_OPTIONS. If this is not
possible, you will need the \.

Gerald



---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


Re: Deep Recursion

Posted by Nate Smith <na...@thebackrow.net>.
On Sun, Jul 21, 2002 at 03:25:03PM +0200, Gerald Richter wrote:
> >
> > I am not having much luck getting a recursive function to work as it
> > should.
> 
> You need to localize your variables, otherwise they will be overwritten by
> the second call the the sub:

When I do this, it appears as if it is not even processing the [* *] 
sections.  Does it matter that I'm using EmbperlObject?  I also get
no debugging info output into embperl.log.  

The guts of what I'm doing follows:

 <table border=1>
 <tr> <td> &nbsp </td></tr>
    [- 
      #Execute ({sub => 'printTree', param => ['0', '0'] });
      printTree(0, 0); 
    -]
 </table>


[$ sub printTree $]

  [*
   local ($parent, $depth) = (@_) ? @_: (0,0);
   local $sth = $dbh->prepare( "select id, data from to_do where child_of = '$parent'" ); 
         $sth->execute();
   local %data = ();
   while ( local ($child, $data) = $sth->fetchrow_array() ) {
     $data{$child}{data} = $data;
     $data{$child}{depth} = $depth;
   }
  *]
  <pre>
  [- print OUT Dumper \%data -]
  </pre>
  [$ foreach $thing (sort keys %data) $]
   <tr> <td> 
     [- 
      print OUT "--" x $data{$thing}{depth};
     -]
     [+ $thing +] :: [+ $data{$thing}{data} +] 
   </td></tr>
   [-
     local $sth2 = $dbh->prepare( "select count(*) from to_do where child_of = '$thing'" );
           $sth2->execute();
     my ($children) = $sth2->fetchrow_array();
     if ($children > 0) {
        my $newDepth = $data{$thing}{depth} + 1;
        #Execute ({ sub => 'printTree', param => [$thing, $newDepth] });
        printTree($thing, $newDepth);
     } else {
     }
   -]
  [$ endforeach $]
[$ endsub $]

> 
> >
> > [$ sub printTree $]
> [*
> local $parent ;
> local $depth ;
> local $sth ;
> # add all variables here, that are declared with  my in the Perl version
> *]
> >   [-
> >    ($parent, $depth) = @_;
> >    print OUT "In PrintTree with depth = $depth, parent = $parent\n";
> .....
> 
> Note 1: You cannot use my here, because of the way EMbperl 1.3.x work
> internaly (with EMbperl 2, you can use my)
> Note 2: The local must be in a [* *] block, so the scope of the local is the
> whole sub.
> Note 3: Also [* *] are experimental in 1.3.4, it works without problems in
> this case
> 
> Gerald
> 
> 
> -------------------------------------------------------------
> Gerald Richter    ecos electronic communication services gmbh
> Internetconnect * Webserver/-design/-datenbanken * Consulting
> 
> Post:       Tulpenstrasse 5         D-55276 Dienheim b. Mainz
> E-Mail:     richter@ecos.de         Voice:    +49 6133 925131
> WWW:        http://www.ecos.de      Fax:      +49 6133 925152
> -------------------------------------------------------------
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
> For additional commands, e-mail: embperl-help@perl.apache.org
> 

-- 
"Why do so many otherwise intelligent people look for answers to serious 
 questions in systems purely of their own devising, which are able to prove 
 on their own terms that they don't even have them? Mathematics, logic, 
 science: they're useful servants, but exceptionally bad masters."
                                           --Simon Cozens

---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


Re: Deep Recursion

Posted by Gerald Richter <ri...@ecos.de>.
>
> I am not having much luck getting a recursive function to work as it
> should.

You need to localize your variables, otherwise they will be overwritten by
the second call the the sub:

>
> [$ sub printTree $]
[*
local $parent ;
local $depth ;
local $sth ;
# add all variables here, that are declared with  my in the Perl version
*]
>   [-
>    ($parent, $depth) = @_;
>    print OUT "In PrintTree with depth = $depth, parent = $parent\n";
.....

Note 1: You cannot use my here, because of the way EMbperl 1.3.x work
internaly (with EMbperl 2, you can use my)
Note 2: The local must be in a [* *] block, so the scope of the local is the
whole sub.
Note 3: Also [* *] are experimental in 1.3.4, it works without problems in
this case

Gerald


-------------------------------------------------------------
Gerald Richter    ecos electronic communication services gmbh
Internetconnect * Webserver/-design/-datenbanken * Consulting

Post:       Tulpenstrasse 5         D-55276 Dienheim b. Mainz
E-Mail:     richter@ecos.de         Voice:    +49 6133 925131
WWW:        http://www.ecos.de      Fax:      +49 6133 925152
-------------------------------------------------------------




---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org


Re: Deep Recursion

Posted by Nate Smith <na...@thebackrow.net>.
On Fri, Jul 19, 2002 at 03:47:31PM -0400, Nate Smith wrote:
> The calls to printTree using Execute are commented out since when I use
> those it returns an invalid response and my access_log recieves these:

I forgot to include the fact that if I use the direct-call method, i.e:
  printTree($child, $newDepth);
It fails when the subroutine returns for the second iteration of the
while loop with this error:

[warn] [2249]ERR:  32:  Warning in Perl code: DBD::mysql::st
fetchrow_array failed: fetch() without execute() at line 39


Nate

---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org