thran has asked for the wisdom of the Perl Monks concerning the following question:

I have come seeking the wisdom of the perl monks, because my BBS keeps running out of memory after a brief while of usage. The code is located inside my scratchpad, for it was too big to put on the board. What ways are there for me to improve my code without altering too much? Id be much grateful if I can fix this problem :)

Replies are listed 'Best First'.
(tye)Re: Out of memory
by tye (Sage) on Oct 02, 2001 at 01:59 UTC

    You have implemented an "infinite-stack state machine". (: You have several cases of, you want to "do_this and then do_that" so you write code that says:

    sub do_this { ... &do_that; }
    which means that you won't return from do_this() until you have finished do_that() but do_that() does the same thing so each time you do something new you tie up a new slot on the stack for a subroutine that will never return.

    You really need to replace at least one set of these calls with a loop.

    It would also help to indent your code and read up on "here doc"s (in "perldoc perldata") for large blocks of text. And please use &mysub(); instead of &mysub; (see (tye)Re: A question of style for more on that).

            - tye (but my friends call me "Tye")
Re: Out of memory
by perrin (Chancellor) on Oct 02, 2001 at 02:01 UTC
    The first thing you should do is read the section on this in the Camel Book (Programming Perl).
(jeffa) Re: Out of memory
by jeffa (Bishop) on Oct 03, 2001 at 00:32 UTC
    Here are some suggestions on printing multilines such as ASCII art.


    Try #1

    Simply encapsultate all your print statements in a subroutine - since you are printing to a socket ($client) you should pass it as an arg to the sub - notice my use of whitespace to INDENT the code inside the BRACES:
    sub print_sucky_bunny { my ($client) = shift @_; print $client "\n\r "; print $client "\n\r /| __ "; print $client "\n\r / | ,-~ / "; print $client "\n\r Y :| // / "; print $client "\n\r | jj /( .^ "; print $client "\n\r >-\"~\"-v\" "; print $client "\n\r / Y "; print $client "\n\r jo o | I a +m a sucky ASCII Art bunny"; print $client "\n\r ( ~T~ j And + i am filling in temporarily"; print $client "\n\r >._-' _./ So +if you dont like me"; print $client "\n\r / \"~\" | You + can suck my ****"; print $client "\n\r Y _, | "; print $client "\n\r /| ;-\"~ _ l "; print $client "\n\r / l/ ,-\"~ \\ "; print $client "\n\r \\//\\/ .- \\ "; print $client "\n\r R / Y "; print $client "\n\r O I ! "; print $client "\n\r W _\ /\"\ "; print $client "\n\r (\" ~----( ~ Y. ) "; }
    But printing inside a sub like this is not very modular, imagine if you wanted to store the ASCII art in a variable for latter use - this would always print! So, lets use a scalar instead:


    Try #3

    WAIT FOR IT!!!


    Try #2

    sub create_sucky_bunny { my $bunny; $bunny .= "\n\r "; $bunny .= "\n\r /| __ "; $bunny .= "\n\r / | ,-~ / "; $bunny .= "\n\r Y :| // / "; $bunny .= "\n\r | jj /( .^ "; $bunny .= "\n\r >-\"~\"-v\" "; $bunny .= "\n\r / Y "; $bunny .= "\n\r jo o | "; $bunny .= "\n\r ( ~T~ j "; $bunny .= "\n\r >._-' _./ "; $bunny .= "\n\r / \"~\" | "; $bunny .= "\n\r Y _, | "; $bunny .= "\n\r /| ;-\"~ _ l "; $bunny .= "\n\r / l/ ,-\"~ \\ "; $bunny .= "\n\r \\//\\/ .- \\ "; $bunny .= "\n\r R / Y "; $bunny .= "\n\r O I ! "; $bunny .= "\n\r W _\ /\"\"; $bunny .= "\n\r (\" ~----( ~ Y. ) "; return $bunny; }
    Now we are getting somewhere - we can now use this subroutine (notice that the name changed to reflect it's PURPOSE) 2 ways:
    my $ascii_bunny = create_bunny(); # or print $client create_bunny();
    Much better. But that looks like Java code - ick. Perl is smarter, and doesn't restrict us to having to break strings across multiple lines, we can do this:
    my $foo = "bar baz qux "; # look ma, no \n's!!
    Perl also provides the q() operator, which is just like single quotes:
    my $foo = q(bar baz qux );
    The cool thing about q() is you can use other chars as delimiters -  q{cool} q/cool/ q#cool# q{cool}. Since bunny does not contain any braces in it's ASCII art, we can safely use it for . . .

    Try #3

    Here i use the q() (AKA, q{}) operator to get the ASCII art into $bunny, then i use the s/// operator to add leading space (notice the x operator where $spaces is defined) as well as append \r to each line (\n is already there!). i also removed all backslashes that were being used to escape meta-characters - as a result, the bunny was harmed:
    sub create_bunny { my $spaces = ' ' x 20; my $bunny = q{ /| __ / | ,-~ / Y :| // / | jj /( .^ >-"~"-v" / Y jo o | I'm an ASCII Art bunny ( ~T~ j And i'm fillin' in temporarilay >._-' _./ But at least i can that i / "~" | Was created in a more Perl-ish way! Y _, | (did i just say that out loud?) /| ;-"~ _ l / l/ ,-"~ \ / / / .- \ R / Y O I ! W _\ /"\ (" ~----( ~ Y. ) }; $bunny =~ s/(.*)/$spaces$1\r/g; return $bunny; } print $client create_bunny();
    Be sure and read up on q() and it's cousins, qq(), qr(), and qx() at perlop.

    jeffa