This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What does the function declaration “sub function($$)” mean?
sub t(&#) {
print #_;
}
t {print 1};
I tried to change &# to &$ and it will fail.
What's the lingo for it so that I can search?
&# is a subroutine prototype. This lets you create syntax similar to the builtin grep function (accepts a BLOCK and then a LIST). The LIST can even be the empty list: ().
&$ when used will force the second argument (which is mandatory) to be evaluated in scalar context. Since there is no second argument in t {print 1}; it will fail to compile.
Read more about subroutine prototypes at: perldoc perlsub.
I'm not quite clear on what you want the code to do, but you are creating a prototype for your sub, see the perldocs. The & means the sub t takes a block as the first argument and the # means the rest of the arguments are an array.
When you call your function, you are passing it one argument, the block {print 1} and that is what you are then printing out - the CODE reference as a string. The reason &$ fails is you are not passing a second argument. That is fine for &# as the second argument is the empty array.
The term you are looking for is "perl function prototypes".
"Function prototype", http://perldoc.perl.org/perlsub.html#Prototypes
Related
I've been using the implementation of uniq shown here for a couple of years in various scripts, and I just realized I don't understand how it's returning an array.
That implementation is as follows:
sub uniq {
my %seen;
grep !$seen{$_}++, #_;
}
my #array = qw(one two three two three);
my #filtered = uniq(#array);
Can someone explain how that two line sub is returning an array that gets assigned to #filtered? I.e. why do we not need to take some result from the grep line and return it?
Looking at the sub itself in isolation, my assumption would have been that the grep line was operating on an array passed by reference, #_, and that the calling line could just be uniq(#array);, with #array being modified after that call.
This is purely for my own understanding, I've got no beef with the functionality of this sub, which I've been using with great success.
why do we not need to take some result from the grep line and return it
You do, and are. See perldoc perlsub:
If no "return" is found and if the last statement is an expression, its value is returned.
It's not clear which part of the subroutine you're not understanding. But before we look at the subroutine, a brief aside about terminology.
In Perl "lists" and "arrays" are two different things. And a subroutine only ever returns a list, not an array. The fact that you then store the returned list into the array #filtered makes no difference - what you originally got back from the subroutine was a list.
With that in mind, let's look at your subroutine.
You pass in the array, #array. The contents of that array are put into #_ and passed to the subroutine.
You then use grep on your input array, #_. grep acts as a list filter - it takes a list as input and returns a (probably shorter) list as output. So you get a list of values as the output from grep.
As your subroutine doesn't have an explicit return statement, it returns the value of the final statement executed in the subroutine. That's the grep statement, so the subroutine returns the list that was returned from the grep.
You then take the list that was returned from your subroutine and store it in #filtered.
Does that help at all?
The title of this post says it all. The point is that the calling function X should be agnostic about the signature of the called function Y. IOW, X should just pass to Y, en masse, all the arguments it (X) received, at leave it up to Y to complain if the signature is off.
I thought this was just a matter of
sub X {
return Y( #_ );
}
...but apparently not:
sub getpwuid_wrapper {
return getpwuid( #_ );
}
The wrapper above is doing more than merely wrapping:
DB<7> p getpwuid( 5 )
gamesx560games/usr/games/usr/sbin/nologin
DB<8> p getpwuid_wrapper( 5 )
daemonx11daemon/usr/sbin/usr/sbin/nologin
The next bit gives a clue to what may be going on:
DB<9> p getpwuid( 1 )
daemonx11daemon/usr/sbin/usr/sbin/nologin
I figure that getpwuid( #_ ) is getting interpreted as getpwuid( scalar #_ ), for reasons beyond my comprehension.
NOTE: getpwuid is just an example to illustrate the problem. In practice one needs this sort of pass-through functionality primarily when the function that will be called is not known until runtime; e.g. when this function is a callback.
The problem you are facing is because getpwuid has a prototype of $, which causes it to interpret its parameter in scalar context.
You can see this from the following one-liner:
perl -e 'print prototype("CORE::getpwuid"), "\n"'
...which prints $.
So when you pass #_ to getpwuid, you are correct; it's being taken in scalar context and passing a count of how many elements #_ contains.
One solution is to use the subroutine form of goto, which calls its operand with the same call stack and parameters that were passed to its caller.
Here's an example in the form of a one-liner:
perl -e 'print getpwuid(5), "\n"; print sub{ getpwuid(#_) }->(5), "\n"; print sub { goto &CORE::getpwuid }->(5), "\n";'
In this example, the first and third calls will pass '5' to getpwuid, but the second call will pass scalar(#_), which is 1 in this case.
Another hackish option would be to detect whether the function you are calling has a prototype using the prototype function, and react accordingly. But that's problematic. First, you already know you're calling getpwuid -- no need to detect at runtime. And even if you had to detect at runtime for some reason, some CORE:: functions will return undef for their prototype because they use one that cannot be expressed in terms of the prototype options available to us (system, for example).
In this specific case since you already know what function you are calling, and already know its prototype, it's probably just easiest to do this:
perl -e 'print sub { getpwuid(shift) }->(5), "\n";'
Update: Where the subroutine being called isn't known until runtime goto may be a good means. One of the things you have to look out for with goto, however, is that you never return back to the parent sub; the subroutine being gone-to will return directly to the caller of the parent sub.
Another option is to call the target sub with the & prefix and no parameters. This also serves to pass #_ through to it, but in a way that bypasses prototypes. Here's an example:
perl -e 'print sub { &CORE::getpwuid }->(5)'
This will appear similar to the goto approach, but will not tinker with the call stack, and will return back to the parent sub.
What is Difference between Function and subroutine in perl ?
I found difference in few site, there i found Subroutine does not return value but function returns but actually Subroutine also return value .
Please let me know What is Exact difference between Function and subroutine in perl ?
Generally in computer science a function is a special type of subroutine that returns a values (as opposed to being called just for its side-effects). But in Perl (as the cookbook says) we don't make that distinction.
The two words mean the same thing. They're synonyms.
Course: Perlmonks.
Update:
They are synonyms only because Perl returns last value of expression, evaluated in sub-block.
The following file does not compile:
sub s {
return 'foo';
}
sub foo {
my $s = s();
return $s if $s;
return 'baz?';
}
The error from perl -c is:
syntax error at foobar.pl line 5 near "return"
(Might be a runaway multi-line ;; string starting on line 3)
foobar.pl had compilation errors.
But if I replace s() with &s() it works fine. Can you explain why?
The & prefix definitively says you want to call your own function called "s", rather than any built-in with the same name. In this case, it's confusing it for a substitution operator (like $stuff =~ s///;, which can also be written s()()).
Here's a PerlMonks discussion about what the ampersand does.
The problem you have, as has already been pointed out, is that s() is interpreted as the s/// substitution operator. Prefixing the function name with an ampersand is a workaround, although I would not say necessarily the correct one. In perldoc perlsub the following is said about calling subroutines:
NAME(LIST); # & is optional with parentheses.
NAME LIST; # Parentheses optional if predeclared/imported.
&NAME(LIST); # Circumvent prototypes.
&NAME; # Makes current #_ visible to called subroutine.
What the ampersand does here is merely to distinguish between the built-in function and your own.
The "proper" way to deal with this, apart from renaming your subroutine, is to realize what's going on under the surface. When you say
s();
What you are really saying is
CORE::s();
When what you mean is
main::s();
my $s = 's'->();
works too--oddly enough with strict on.
This question already has answers here:
What does the function declaration "sub function($$)" mean?
(2 answers)
Closed 7 years ago.
What dose the ( $$ ) do in this code. I have programmed Perl for a long time but never came across this syntax until recently when I opened a very old Perl .plx file
These rows prevent me from upgrading to a more modern Perl version.
sub help( $$ ){
}
The reason it affects me is because I get an error message stating that the help function was called before it was declared. Any idea of how I can solve this without removing the ( $$ ) block??
The are called prototypes. This particular one says that the sub routine expects to be called with exactly 2 scalar variables. Although prototypes are sometimes useful, mostly they are not.
If you can drop them depends on the rest of the code...
That's a function prototype, which is used to specify the number and types of arguments that the subroutine takes. See the documentation.
Since it's in the current documentation, I don't see why it's preventing you from upgrading.
Is the error you're getting help called too early to check prototype? Here's the explanation from the perldiag documentation:
(W prototype) You've called a function that has a prototype before the parser saw a definition or declaration for it, and Perl could not check that the call conforms to the prototype. You need to either add an early prototype declaration for the subroutine in question, or move the subroutine definition ahead of the call to get proper prototype checking. Alternatively, if you are certain that you're calling the function correctly, you may put an ampersand before the name to avoid the warning. See perlsub.
It's a prototype. The $$ specifies that the help function expects two arguments and that they should each be evaluated in scalar context. Note that this does not mean that they are scalar values! Perl's prototypes aren't like prototypes in other languages. They allow you to define functions that behave like built-in functions: parentheses are optional and context is imposed on the arguments.
sub f($$) { print "#_\n" }
my #a = ('a' .. 'c');
f(#a, 'd'); # prints "3 d"
I'm guessing that the error message you're seeing is
help() called too early to check prototype
which means that Perl saw a call to the function before it saw the declaration of the function and knew about the prototype. This means that the prototype wasn't enforced and the call may not behave as expected.
my #a = ('a' .. 'c');
f(#a, 'd'); # prints "a b c d"
sub f($$) { print "#_\n" }
To fix the error you need to either move the subroutine definition before the call, or add a declaration before the call.
sub f($$); # forward declaration
my #a = ('a' .. 'c');
f(#a, 'd'); # prints "3 d"
sub f($$) { print "#_\n" }
All of this should have absolutely nothing to do with your ability to upgrade to a newer version of Perl.