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

Prototype mismatch: sub main::trim: none vs ($) at mysqlDB_serial.pl line 188.

here is the code

sub trim($) { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } # Left trim function to remove leading whitespace sub ltrim($) { my $string = shift; $string =~ s/^\s+//; return $string; } # Right trim function to remove trailing whitespace sub rtrim($) { my $string = shift; $string =~ s/\s+$//; return $string; }

Replies are listed 'Best First'.
Re: Prototype mismatch: sub main::trim: none vs ($)
by haukex (Archbishop) on Feb 08, 2017 at 13:50 UTC

    Hi bNathan,

    The code you've shown (please use <code> tags!) is not enough to reproduce the error you describe. See SSCCE and How do I post a question effectively?

    Tip #1 from the Basic debugging checklist: use strict; use warnings; use diagnostics;. This would have told you (emphasis mine):

    The subroutine being declared or defined had previously been declared or defined with a different function prototype.

    I can reproduce the error you describe via:

    $ perl -e 'sub trim {} sub trim($) {}' Prototype mismatch: sub main::trim: none vs ($) at -e line 1.

    Which tells me that you've probably got two sub trims in your code (Update: or, as choroba noted in the reply, one of them could be coming from a module). You'll need to track down this duplicate definition and resolve it somehow, probably by removing or renaming one of the subs.

    I'm guessing that you may not have warnings turned on (Use strict and warnings!), because otherwise you'd have been warned more explicitly:

    $ perl -we 'sub trim {} sub trim($) {}' Prototype mismatch: sub main::trim: none vs ($) at -e line 1. Subroutine trim redefined at -e line 1.

    Hope this helps,
    -- Hauke D

      > Which tells me that you've probably got two sub trims in your code.

      Note that the first instance of trim could have been imported from a module, so there's in fact only one explicit declaration in the code.

      #!/usr/bin/perl use warnings; use strict; { package My; use Exporter qw{ import }; our @EXPORT = qw { trim }; sub trim { 1 } } 'My'->import; # Same as "use My;" if My was declared in My.pm sub trim ($) { 2 }

      ($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,
Re: Prototype mismatch: sub main::trim: none vs ($) at mysqlDB_serial.pl line 188.
by Eily (Monsignor) on Feb 08, 2017 at 14:13 UTC

    ++haukex, on everything.

    It looks like you found those functions on the internet as a way to trim whitespace from strings. I searched "Left trim function to remove leading whitespace" on Google to see where it came from, and while I saw a few pages where those functions were presented as one way to do that, none had a description of the effects of the ($) prototype. While "an extra check of the parameters" may sound like a good idea, this prototype also forces scalar context on the first (and only) argument, and turns the function into an unary operator. Since prototypes are rarely used, this means that those three functions will not behave like most other subs you'll use (at least the ones from other modules). To avoid surprises, you should remove the ($) after the names trim, ltrim and rtrim.

      Hi Eily,

      Excellent point on bringing attention to the prototype!

      ... those three functions will not behave like most other subs you'll use (at least the ones from other modules). To avoid surprises, you should remove the ($) after the names of your subs.

      I think a trim function would make sense as a unary operator, that would put it in the same category as lc, lcfirst, uc, ucfirst, fc, length, chr, hex, oct, int, ref, scalar, and quite a few more. But this is definitely another one of those "do this only if you know what you're doing and why" cases. (Just the other day there was a thread on the same topic.)

      Regards,
      -- Hauke D

        I agree on the fact that a trim function could make sense as an unary operator. I think the problem is mostly that this was not documented, although the code seems to be meant to be shared. Personally though, I prefer only using the special case of the & prototype, where the special block syntax would be invalid without the prototype, removing the need to know how the function was declared to read a statment correctly.

Re: Prototype mismatch: sub main::trim: none vs ($) at mysqlDB_serial.pl line 188.
by hippo (Archbishop) on Feb 08, 2017 at 15:27 UTC

    ++haukex on everything from me too.

    Did you (bNathan) know that these three functions already exist? They are part of String::Util so there is no need to reinvent the wheel. Remember that laziness is one of the three great virtues.

      Hi hippo & bNathan,

      Or, just use the regexes directly ;-)

      $string =~ s/^\s+//; # ltrim $string =~ s/\s+$//; # rtrim $string =~ s/^\s+|\s+$//g; # trim

      Regards,
      -- Hauke D

        As a nit, Perl FAQ trimming spaces says that running both the 2 regex'es above (ltrim and rtrim) is faster than the single regex trim. This post on StackOverflow Why is single regex slower? goes into more detail about exactly why that is true.

        These 2 lines are such an idiom that I just type them from memory without needing to use a sub. With Perl, not every "shorter" formulation is faster.