Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

$_ functions vs argument-using functions

by pldanutz (Acolyte)
on Sep 09, 2013 at 18:43 UTC ( #1053069=perlquestion: print w/ replies, xml ) Need Help??
pldanutz has asked for the wisdom of the Perl Monks concerning the following question:

By $_-using functions, I mean functions that take their argument from the implicit variable $_, instead of relying on "actual" arguments that a sub receives in @_

Some second-order functions (e.g. map, as I learned in map sub to list?) prefer $_-using functions, instead of functions that use their @_ arguments:

Is one style preferred over the other in general? How can I convert between them?

sub f1 ($) { shift(@_) + 1 } sub f2 { $_ + 1 } map (f1($), (10, 20)) # convert f1 to $_-style my $x = f1 (10) # call f1 with an arg # my $y = f2 (10) # won't work, how to use f2??
P.S. How do I even search for stuff like this? I'm sure others must have asked this before.

Comment on $_ functions vs argument-using functions
Download Code
Replies are listed 'Best First'.
Re: $_ functions vs argument-using functions
by LanX (Canon) on Sep 09, 2013 at 18:58 UTC
    ok, some sources of confusion

    1. Perl has -alas - no function signatures, nothing like sub f($a,$b) {...}
    2. don't use prototypes before you know what you are doing, avoid sub f($) {...}
    3. the default variable $_is not primarily meant for functions.

    see perlsub for subs and prototypes.

    see perlvar (and perlsyn for $_

    see perlfunc for builtin functions

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      I understand that the prototype sub f ($) {} makes sure f is called with exactly one argument. I know I can't have formal args, but can use my ($a, $b) = @_ instead (or shift @_)

      I know what $_ is used for, the way it gets its value in while (<>) and the way it is used implicitly in m/PATTERN/ and chomp. But I see that it can be used instead of function arguments (e.g. map prefers such functions). And I was asking if that was a preferred style.

        > (e.g. map prefers such functions)

        thats a misunderstanding, because the normal (ok nowadays recommended) way to use map is with a block using the default var. So "map prefers blocks"!

        From this point of view writing map { f($_) } 1..3 is the canonical approach!

        But this means overhead, because map calls now two functions in a row (the block means an anonymous function).

        To avoid this, some experts prefer using the EXPR syntax  map f, 1..3 which is magic (which means a parsing exception introduced for DWIM and syntactic sugar).

        Because a bareword in Perl almost always means a function call², if you need the function reference of f you need to write \&f, but some builtins like map and grep magically (sic) accept expressions.

        Since you are replacing the block with f you have to mimic the behaviour to use $_ - a localized global variable - in the function body.¹

        Your problems understanding all of this derive from the fact that you are starting with the rare syntax exceptions.

        Clearer now?

        (BTW: I always wanted to write a cross-manual explaining Perl vs JS, to highlight the details in both languages, but somehow all people told me there is no need... )

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        ¹) The trick with the (_) prototype is rather new, it passes $_ into @_ if an argument is missing.

        ²) opposed to languages like JavaScript where a bare f is ALWAYS the reference of function f(a,b,c){ ... }

        update

        if you are interested in functional programming, try having a look into *Higher Order Perl* - you can download it for free.

        I understand that the prototype sub f ($) {} makes sure f is called with exactly one argument.

        Sorry, but that's not true:

        #!/usr/bin/perl use strict; use warnings; sub f($) { print 'f called with ',0+@_,' arguments: ',join(', ',@_),"\n"; } sub g { print 'via g: '; &f; } f(42); &f(42); &f(); &f(42,99,333); g(42); g(); g(42,99,333);

        Output:

        f called with 1 arguments: 42 f called with 1 arguments: 42 f called with 0 arguments: f called with 3 arguments: 42, 99, 333 via g: f called with 1 arguments: 42 via g: f called with 0 arguments: via g: f called with 3 arguments: 42, 99, 333

        See perlsub for what happens here, and why perl does not complain.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: $_ functions vs argument-using functions
by tobyink (Abbot) on Sep 09, 2013 at 21:11 UTC

    Using $_ as the primary method of passing parameters to a function does not seem like good style to me. A common pattern amongst Perl's built-ins though is to pass a parameter, but use $_ when no parameter is passed. A la:

    sub f3 { my $input = @_ ? shift : $_; return $input + 1; }

    If you're using a vaguely recent version of Perl, the underscore prototype makes this simpler (and magically works with lexical $_):

    sub f4 (_) { my $input = shift; return $input + 1; }
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: $_ functions vs argument-using functions
by Generoso (Parson) on Sep 09, 2013 at 19:04 UTC

    Apologies this answer is for an other question.

Re: $_ functions vs argument-using functions
by Jenda (Abbot) on Sep 10, 2013 at 13:49 UTC
    map (f1($_), (10, 20)) # convert f1 to $_-style my $x = do {local $_ = 10; f2}; # or, if you just want to call that subroutine, f2 for (15);

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1053069]
Approved by Old_Gray_Bear
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (16)
As of 2015-07-30 21:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (273 votes), past polls