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

Anyone got an example of using the (_) prototype?

All the docs say is:

As the last character of a prototype, or just before a semicolon, you can use _ in place of $: if this argument is not provided, $_ will be used instead.

Which doesn't explain (to me) how it is used?


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: Prototype (_)?
by Corion (Patriarch) on Dec 04, 2014 at 12:25 UTC

    The idea is to recreate the effect of (say) how the length function is parsed:

    #!perl -w use 5.010; sub mylength(_) { length($_[0]); }; for('a','aa','aaa') { say "length :", length; say "mylength :", mylength; say "mylength :", mylength($_); };
      sub mylength(_) { length($_[0]); };

      Ah! So you use the positional form of the argument (ie. $_[n]) and if that position is unpopulated, perl supplies the value of $_.

      Got it. (Some mention of using $_[n] in the docs would be good :)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Well, as long as you don't change the value it would work the same with shift. Since you've had exemple already, and I'm not sure of what's troubling you, I'll try to answer a question you didn't ask: why? (or when?). In the best case, it'll help you, in a less optimal case, it'll help others, in the worst case scenario, someone will be able to correct one of my misconceptions :D

        In most case, the prototype _ as a simple prototype-less equivalent:

        sub prototyped($_;$) { # Here $_[0] is a compulsory argument # $_[1] defaults to $_ # $_[2] may not even exist } sub unprototyped { push @_, $_ if @_ < 2; # Here $_[0] is a compulsory argument # $_[1] defaults to $_ # $_[2] may not even exist }
        Here I used the prototype $, but _ of course works after \@, \%, + ... (but you can't have an unprototyped equivalent without using source filters)

        Now, that's probably enough in most cases, but this might cause some trouble if the function should modify its parameters (like chomp), or if $_ is a tied scalar (you'll call FETCH, which might have unexpected side effects) you can't just push a copy into @_. In this case, the best equivalent code I could come up with (using only core perl) is:

        sub unprototyped { goto &unprototyped @_, $_ unless @_ > 1; # See comments in previous exemples }
        Now that's where the _ becomes really useful, because not using goto will run faster, and will prevent people who can't tell the difference between the C-style and the other goto from calling you the devil.

        NB: for the '$_ is tied or should be modified' problem, an alias would work (but it is not core perl) but not this:

        sub unprototyped { push @_, $_ if @_ < 2; # Do all the work $_ = $_[-1]; # Return value here }
        Because in '# Do all the work', the modifications and copies of $_ won't trigger STORE and FETCH. A reference to either the parameter or $_ would work though, but it wouldn't be as transparent.

        And there is another case where push @_, $_ is not equivalent to the _ prototype, I'll leave this bit of code to show how _ can go wrong:

        use v5.14; sub f2 { while (<DATA>) { chomp; last; }; } sub f1(_) { f2; say shift; } f1 "Hello "; $_ = "World"; f1; f1 for "!"; __DATA__ Everyone Perlmonks

        Edit: of course, in all my exemples the user plays nice and never calls unprototyped without arguments.

        Args are passed via @_. This is documented.
Re: Prototype (_)?
by Athanasius (Archbishop) on Dec 04, 2014 at 12:29 UTC

    From the Camel Book (4th Edition, 2012), page 328:

    As the last character of a prototype, or just before a semicolon, you can use _ in place of $. If this argument is not provided, the current $_ variable will be used instead. For example:

    sub mymkdir(_;$) { my $dirname = shift(); my $mask = @_ ? shift() : 0777; my $mode = $mask &~ umask(); ... } mymkdir($path, 01750); mymkdir($path); mymkdir(); # passes in $_

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Prototype (_)?
by choroba (Cardinal) on Dec 04, 2014 at 12:25 UTC
    It enables you to create functions that behave like length, for example.
    print prototype 'CORE::length';
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      I know what it is meant to do; I just don't get from the description how to use it.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.