in reply to Re^3: perl and apache2 on ubuntu 17.04
in thread perl and apache2 on ubuntu 17.04

there is giant reason i use prototypes. but, i would like to know WHY it's such a giant deal that i do.

Please see Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen. Just to briefly name a few issues, Prototypes do much more than just check how many arguments are passed to a function, they also affect how Perl code is parsed and how arguments are passed to functions (e.g. arrays are magically turned into arrayrefs where normally they would get flattened). If you have "lots of subs in many different modules", can you recall what the prototype of each and every one is? How about someone else using your code, or a future maintainer, will they be surprised at how their code gets parsed? Plus, just call a sub as &foo(...) and the prototype is ignored, and they're also not used for method calls.

Note I'm not saying you shouldn't ever use them. But they're not really meant as a "check the number of arguments passed to a sub" feature, for that you've got @_==3 or croak "bad number of args to X", modules like Params::Validate, or even the experimental Signatures. Prototypes are best for functions that extend the Perl syntax (e.g. the way Try::Tiny does it), and if you do use them, you should be aware of all of the issues.

Replies are listed 'Best First'.
Re^5: perl and apache2 on ubuntu 17.04
by jamroll (Beadle) on Jul 19, 2017 at 13:57 UTC

    i see. i will read that Tom Christiansen doc... i like the prototyping, and i don't expect anyone to be maintaining my code...i literally am a one man band here. besides, i'm 100% certain anyone who comes along to maintain my code...would start totally anew. eg?

    this code just verifies user's email input is valid (of course, doesn't check if email address exists or not) - just confirms conformity
    #!/usr/bin/perl # /var/www/html/verifyemail.pl # must have's! use strict; use warnings; use CGI::Carp qw(fatalsToBrowser); use URI::Escape; use lib "/var/www/html/Pm"; use Bc_misc qw(get_param); use Bc_sql qw(sql_connect sql_execute sql_disconnect); my $e = uri_unescape(get_param("e")); $e =~ s/(\!|\#|\$|\%|\&|\'|\*|\+|\-|\/|\=|\?|\^|\_|\`|\{|\||\}|\~)/\\$ +1/g; my $usable = 1; # start off assuming the email address is valid, even +if it isn't my $DEBUG = 0; print "cache-control: no-cache, no-store\ncontent-type: text/plain\n\n +"; if ($e) { my $db = sql_connect("ns.db"); my $sql = sql_execute($db, "select email from users", "verifyemail.p +l"); # the last param appends to an error msg, if error (so i know wh +at causes the error) if ($sql) { my @users = @$sql; foreach my $userRef (@users) { my %user = %$userRef; if (uri_unescape($user{email}) =~ /^$e$/i) { $usable = 0; } } } sql_disconnect($db); } else { $usable = -1; } # now, check to make sure the email is actually valid if ($usable) { # email addresses already in DB don't need verification...duh # we're just gonna make sure there's only ONE @ symbol, and at least + one dot # first, let's split the address up at the @ my @addy = split(/\@/, $e); # it should only be two pieces if (@addy != 2) { $usable = -2; } else { # okay, so it's got two bits. # now check for double . and leading/trailing dots in both parts o +f addy if ($addy[0] =~ /\.(\.)+/ or $addy[1] =~ /\.(\.)+/ or $addy[0] =~ /^\./ or $addy[1] =~ /^\./ or $addy[0] =~ /\.$/ or $addy[1] =~ /\.$/ or $addy[1] !~ /\./) { $usable = -3; } else { # now, we gotta make sure only valid characters # are in both parts # first, we'll start with the stuff before @ # and then work on the stuff after # remove all valid characters from the email address. # whatever's left over is invalid, unless it's blank! # blank is GOOD my $addy1 = $addy[0]; my $addy2 = $addy[1]; $addy1 =~ s/[a-z]//ig; $addy1 =~ s/[0-9]//ig; # remove `~!#$%^&*-_=+/?{}' $addy1 =~ s/\\\!|\\\#|\\\$|\\\%|\\\&|\\\*|\\\+|\\\-|\\\/|\\\=|\\ +\?|\\\^|\\\_|\\\`|\\\{|\\\||\\\}|\\\~|\\'//g; # ' <-- here to termin +ate the first quote! $addy1 =~ s/\.//g; # and now the stuff after @ $addy2 =~ s/[a-z]//ig; $addy2 =~ s/[0-9]//ig; $addy2 =~ s/\.//g; $addy2 =~ s/-//g; if ($addy1) { $usable = -4; } if ($addy2) { $usable = -5; } } } } if ($DEBUG) { print $usable; print "\n$e"; } else { print $usable; } exit 1;
    and....what's meant by will they be surprised at how their code gets parsed? - parsed? I know what parsing is....but why would my code get parsed??
      > why would my code get parsed??

      Perl parses your code in order to run it. And by using prototypes, you're telling the parser to parse the subroutines differently to the general rules in some contexts (basically without parentheses). Read the linked article and possibly also perlsub for details.

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        ok. i have checked it out. like you said, so long as i adhere to the same methodology, i'm ok. i have some 250+ subroutines in all...and i really don't wanna change all of that code (easy as it may be). besides...doing so might break a library (subdesc.pm) i wrote to read the comments in my libraries (including itself), and creates pretty documentation in HTML format for me! under the hood, the prototype list is used. it's very cool, just don't include the word "return" in a comment, and all's good lol.
        I was pondering why the ball was getting bigger, and then...it hit me!
      i'm 100% certain anyone who comes along to maintain my code...would start totally anew.

      Personally I'd be less certain than that :-)

      Anyway, I took a quick look at your code, and it looks like you're using parentheses on your function calls, which mitigates some of the parsing issues I touched on in Fun with Prototypes - as long as you're consistent in your style! But still, I'd suggest you look into Signatures instead of prototypes, which were discussed e.g. in this recent thread (Update: or some of the other options I mentioned).