in reply to How am i doing?

So, like ikegami pointed out, always start your Perl programs with the following three lines:

#!/usr/bin/perl
use strict;
use warnings;

I also like to add:

$| = 1;

because it turns off buffering stdout, which means when you print something, it will immediately appear on the screen. Normally, when you print something, Perl will capture it and hold it in a buffer, and when the buffer gets full, then it will print it. So, you may get weird results where part of your program that you expect to produce some output appears to do nothing. So, basically, I always start my Perl programs with these four lines. The "use strict" and "use warnings" help you avoid weird problems in coding..

my $result = 0;

sub fib
{
 my  @frame = @_;

Note: When you are referring to a single element of an array or list, always put a $ sign in front of it instead of a @. When you use @ in front of an array or list, it means that you are referring to all of the elements. So, this code:

# @frame[0] = @frame[0] + @frame[1]; # @frame[1] = @frame[2]; # @frame[3] = @frame[2]; is better written as: $frame[0] += $frame[1]; $frame[1] = $frame[2]; $frame[3] = $frame[2]; You may notice that I also changed @frame[0] = @frame[0] + @frame[1]; to $frame[0] += $frame[1]; just because it is shorter and nicer. count($frame[0]);

Now, this is not a syntax error, but it's a program design error. Here in the next line you are calling the sub-routine itself, which can cause problems. If you call a sub-routine from within itself many times, that's often a bug. Why? Because each time you call a sub-routine, it uses memory. When you exit a sub, that memory is released. But if you call a sub-routine from within itself before exiting, then your program is just using more and more memory without the ability to release it, so this is a design flaw here. When you want to call a sub-routine from within itself, always think about the problem first and see if you can write the code in a different way, because this is leading to an undesired outcome. Here, in this case, your sub-routine is adding 2 to the first $frame[0] each time, and then the function calls itself millions of times. That means you are possibly using more than 10 megabytes of memory just to do this loop. So, try to redesign this code. I would create a for loop here instead.

return fib(@frame) unless($frame[0] >= 4000000); } sub count { my $increment = @_; if(($increment % 2) == 0) { $result = $result + $increment; } Another thing: When I do division by 2 and I'm looking for the remainder, I always use & 1 instead of % 2 like so: if(($increment & 1) == 0)

Why? Because in the computer's internals, a division or multiplication is always slower than a logical operation. An & is a logical operation, because the processor can perform it in one step. A multiplication or division, on the other hand, can take hundreds of steps. So, you speed up your program if you avoid multiplication and divison whenever you can. In this case when you take a number and apply bitwise AND 1, it will leave you with the last digit, which is the same as dividing it by 2 and taking the remainder.

Or for example, when you are multiplying an integer by 2, I like to use the shift left operator << instead of multiplication. When I divide a number by 2, 4, 8, or 16... I use the shift right operator >> because it's faster. The processor can perform a shift in one step, while a multiplication can take longer, and division takes much longer. Example: $A << 3 is the equivalent of $A * 8

(Note: What I just told you about using bitwise AND and SHIFT only applies to integers under 4 billion. If you are making calculations with really big numbers that are far bigger than 4 billion, then you have to use the multiplication and division signs... ( * / % ). But for small numbers, you can use the bitwise operators ( & << >> ), because they are faster.)

}

fib(1,2,3);
print $result;

You're doing great!!

Replies are listed 'Best First'.
Re^2: How am i doing?
by choroba (Cardinal) on Jul 18, 2025 at 15:33 UTC
    > If you call a sub-routine from within itself many times, that's often a bug.

    Or it might be recursion, which is not a bug.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re^2: How am i doing?
by LanX (Saint) on Jul 20, 2025 at 19:40 UTC
    Please note that Perl has a default warning if the recursion level exceeds 100 (it's configurable somewhere)
    :/tmp$ perl -wE'my $x=0; sub rec { return if ($x++ >= 99); rec()}; rec +()' Deep recursion on subroutine "main::rec" at -e line 1. + # <--- :/tmp$ perl -wE'my $x=0; sub rec { return if ($x++ >= 98); rec()}; rec +()'

    It's true that every recursion can be written with a loop (and more importantly vice versa!).

    But recursions provide very clean maintainable code for many problems and in my experience rarely exceed the 100 threshold, where the memory load is negligible.

    FWIW Larry provided us with goto &sub syntax which allows to (re)call a sub without creating a frame and pushing data on the stack.

    Most importantly:

    Fibonacci is the schoolbook example for with recursive calls and you are WAYYYYYY OFF the mainstream here.

    Even flatearthers might ridicule you as a weird outsider.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      > Fibonacci is the schoolbook example for with recursive calls

      Are you sure? I'm not sure what you mean exactly because of all the prepositions, but implementing the Fibonacci sequence by recursion is very ineffective inefficient. It's a schoolbook example of memoisation and implementing a recursive formula without recursion, I'd say.

      I agree with the rest of your node, though.

      Updated: Thanks LanX.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        ChatGPT agrees, HOW CAN I BE WRONG? ;-P

        Yes, the Fibonacci sequence is a classic example used to illustrate the concept of recursion in computer science and programming. The Fibonacci sequence is defined as follows: - 'F(0) = 0' - 'F(1) = 1' - 'F(n) = F(n-1) + F(n-2) for n > 1' In a recursive implementation, the function calls itself to compute the values of F(n-1) and F(n-2) until it reaches the base cases (F(0) and F(1)). This example effectively demonstrates how recursion works, including the concepts of base cases and recursive cases. However, it's worth noting that while the recursive approach is straightforward, it is not the most efficient way to compute Fibonacci numbers due to its exponential time complexity.

        Yes I'm sure, because I've seen it multiple times used this way, IIRC also in HOP.

        The F(n) = F(n-1) + F(n-2) for n > 1 part is straightforwardly implemented with recursion.

        > implementing the Fibonacci sequence by recursion is very ineffective.

        (Slightly nitpicking) It's inefficient but effective!

        The point is you get a correct result, even if you waste processing power.

        The "memoisation" you mentioned solves this efficiency problem of needlessly recalculating known results.

        IOW, the schoolbook continues evolving the example to deeper depth (sic).

        Keep in mind that the classic MIT lectures on programming used to be in Lisp and original Lisp didn't have loops, only those "tail recursions".

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

      > (it's configurable somewhere)

      Unfortunately it's not, one has to recompile Perl to change that. Mea culpa!

      As a "funny" tangent, I asked ChatGPT and it hallucinated a special variable ${^RECURSION_LIMIT} ... LOL (sic)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery