http://www.perlmonks.org?node_id=740335

I've a few good friends who like Python a lot (yes it is a nice Language, but I like Perl more). One difference is, that you can program in Python without using semicolons. Well, this is possible using the Perl language too, like the following code demonstrates it (it calculates fibonacci numbers, however without use strict). I don't tell, that you will have any benifit by not using a semicolon. But I think this is a funny way of programming in Perl. Enjoy :)
#!/usr/bin/perl { $n = shift || die "Usage: perl nosemicolon.pl NUMBER\n" } sub fib { if ($_[0] < 2) { $_[0] } else { fib($_[0] - 1) + fib($_[0] - 2) } } { print "Fibonacci numbers from 0 to $n are as follows:\n" } for (0 .. $n) { print "fib($_) = ", fib($_), "\n" } print "Thanks for using this software!\n"

Replies are listed 'Best First'.
Re: Programming in Perl without semicolon (strict)
by toolic (Bishop) on Jan 30, 2009 at 22:21 UTC
    To use the strictures, change $n to $ARGV[0] :)
    $ perl -w -Mstrict nosemicolon.pl 5
Re: Programming in Perl without semicolon
by JavaFan (Canon) on Jan 31, 2009 at 02:15 UTC
    With caching (so it runs fast for large numbers), with variables, and not generating warnings/errors if strict and/or warnings were to be turned on:
    {@::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]} }

      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) && ...

        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.

Re: Programming in Perl without semicolon
by ambrus (Abbot) on Feb 09, 2009 at 15:57 UTC

    Or just let perl insert those semicolons for us.

    BEGIN { use Filter::Util::Call; filter_add(sub { + my $s = filter_read(); s/$/;/mg; $s; }); } + use warnings use strict my $n = shift || die "Usage: perl nosemicolon.pl NUMBER\n" sub fib { if ($_[0] < 2) { $_[0] } else { fib($_[0] - 1) + fib($_[0] - 2) } } print "Fibonacci numbers from 0 to $n are as follows:\n" for (0 .. $n) { print "fib($_) = ", fib($_), "\n" } print "Thanks for using this software!\n"
Re: Programming in Perl without semicolon
by Lawliet (Curate) on Jan 30, 2009 at 23:23 UTC

    Haha, well done :)

    However, couldn't you just put every statement in a bare block in any Perl file to accomplish this? Good point, jdporter.

    And you didn't even know bears could type.

      You couldn't put next/last/redo in bare blocks either, at least not without adding labels. Bare blocks are loops that execute once.

      However, that's not a big issue because those commands are practically always used conditionally. Unlike bare blocks, if blocks aren't loops, so you can use if ($cond) { next } (but not { next if $cond }).

      If you do have an unconditional loop control command (e.g. { ...; redo }), label the loop (LOOP: { { ... } redo LOOP }) or use a unconditional if ({ { ... } if (1) { redo } }).

      Notice that he didn't use any my variables?

        Wait a couple seconds! What about use vars()? (ikegami's reply to a reply below made me think of it (because he had used it himself).)

        And you didn't even know bears could type.