in reply to Re: Programming in Perl without semicolon
in thread Programming in Perl without semicolon

Yuck! Use use vars.

{ use vars qw( @cache @n ) } {@cache = (0, 1)} sub fib { {push @n, shift} {return pop @n if $n[-1] < 2} {$cache [$n[-1]] ||= fib ($n[-1] - 1) + fib ($n[-1] - 2)} {return $cache[pop @n]} }

Bonus: Doesn't confine you to the main namespace!


Now if we could only localize variables, we wouldn't need to manage our own stack.

{ use vars qw( @cache ) } {@cache = (0, 1)} sub fib { (local (our $n = shift)) && do { {return $n if $n < 2} {$cache[$n] ||= fib ($n - 1) + fib ($n - 2)} {return $cache[$n]} } }

Bonus: Don't have to use use vars except for globals!


By the way, the body simplifies down to a single expression, and your cache initialiser is not needed.

{ use vars qw( @cache ) } sub fib { (local (our $n) = shift), ( $n < 2 ? $n : $cache[$n] ||= fib ($n - 1) + fib ($n - 2) ) }

Update: Replaced buggy
(local our $n = shift) && ...
with
(local (our $n) = shift) && ...

Replies are listed 'Best First'.
Re^3: Programming in Perl without semicolon
by JavaFan (Canon) on Jan 31, 2009 at 08:37 UTC
    Bonus: Doesn't confine you to the main namespace!
    That's only a bonus if you can switch packages without a semicolon. I haven't figured out how, except for the useless:
    {package Foo}
    (local our $n = shift) && do { ... }
    I'm surprised this works. I would have expected 'our' to be in effect after the statement, just like 'my'. (If you replace 'local our' with 'my', the code wouldn't compile under 'strict').

    Unfortunally, it's not a general technique. It works here because 'fib(0)' is supposed to return '0'; the block isn't executed if the argument of the function is 0.

      That's only a bonus if you can switch packages without a semicolon.

      Oh yeah. Well, no bonus, but it still makes it more readable.

      I'm surprised this works.

      Me too, but it makes sense. It allows for

      our $state = $next_states{$state};

      Unfortunally, it's not a general technique.

      Oops! Just replace the and op with a list op or replace the sassign op with an aassign op.

      (local our $n = shift), ...

      or

      (local (our $n) = shift) && ...

      The former is simpler. The latter has the advantage that it doesn't affect the return value in list context.

      Unfortunally, it's not a general technique. It works here because 'fib(0)' is supposed to return '0'; the block isn't executed if the argument of the function is 0.
      But it can be written as:
      local our ($n, $m) = (shift, 0)) && do { }
      and then it will always do the 'do'.