Subroutines and '&'

B

Bill H

I have always called my subroutines with an '&', Example:

&something;

sub something
{
return;
}

But I see in the perlfaq that the '&' isnt used. Is there any reason I
should / should't be using the '&' or does it just not make a
difference?

Bill H
 
G

Gunnar Hjalmarsson

Bill said:
I have always called my subroutines with an '&', Example:

&something;

sub something
{
return;
}

But I see in the perlfaq that the '&' isnt used. Is there any reason I
should / should't be using the '&' or does it just not make a
difference?

perldoc -q "&foo"
 
R

Randal L. Schwartz

Sherm> It *does* make a difference - if you don't know or understand what that
Sherm> difference is, or you don't specifically want the behavior specified by
Sherm> the &, you shouldn't use it.

Or, for the opposite point of view, if you have:

sub log { print STDERR localtime() . ": @_\n" }

then you better darn well invoke it as:

&log("my message");

and *not*:

log("my message"); # invokes built-in logarithm function

And until you know all the perl built-ins, you should use &. And this
is what we teach in Learning Perl.

Please don't be so quick to dismiss the value of the leading &.
 
R

Randal L. Schwartz

~greg> It is still required,
~greg> but only when dealing with references (I think)

Or when dealing with a subroutine that is the same name as a built-in.
See my other post.
 
P

Paul Lalli

Or, for the opposite point of view, if you have:

sub log { print STDERR localtime() . ": @_\n" }

then you better darn well invoke it as:

&log("my message");

and *not*:

log("my message"); # invokes built-in logarithm function

And until you know all the perl built-ins, you should use &.

The difference, of course, is that failing to use & when required will
generate a pretty explicit warning, while using it when you shouldn't
will not. That's why I generally tell my students this is the one
tiny piece of Learning Perl that I disagree with. :-/

Paul Lalli
 
M

Mirco Wahab

~greg said:
It is still required,
but only when dealing with references (I think)

And nonlocal context 'jumps':

...
sub indirect { print "otherthing\n@_\n" };

sub onething { goto &indirect; print "this wont show up\n" }

onething( qw'A B C' );
...


Regards

M.
 
J

John W. Krahn

Randal said:
Sherm> It *does* make a difference - if you don't know or understand what that
Sherm> difference is, or you don't specifically want the behavior specified by
Sherm> the &, you shouldn't use it.

Or, for the opposite point of view, if you have:

sub log { print STDERR localtime() . ": @_\n" }

then you better darn well invoke it as:

&log("my message");

and *not*:

log("my message"); # invokes built-in logarithm function

And until you know all the perl built-ins, you should use &. And this
is what we teach in Learning Perl.

Please don't be so quick to dismiss the value of the leading &.

Fortunately the syntax highlighting in my editor of choice allows me to
distinguish between built-in functions and user defined subroutines.

:)


John
 
T

trudge

~greg> It is still required,
~greg> but only when dealing with references (I think)

Or when dealing with a subroutine that is the same name as a built-in.
See my other post.

In another situation, I find it most useful as well. For example, I
typically determine what to do in a script by checking an incoming
parameter of a form:

my $MODE=param('Mode');
{
no strict;
$MODE="GetLogin" unless $MODE; # default sub to execute
&$MODE; # else execute this sub
}

This saves a lot of 'if-else' chains. Just my 2 Canadian cents.
 
P

Paul Lalli

I
typically determine what to do in a script by checking an incoming
parameter of a form:

my $MODE=param('Mode');
{
no strict;
$MODE="GetLogin" unless $MODE; # default sub to execute
&$MODE; # else execute this sub

}

This saves a lot of 'if-else' chains. Just my 2 Canadian cents.

It's also a rather absurdly large security whole. You have no way of
knowing what that parameter is. You are making the assumption that
the only way to contact your CGI script is via your form. This is
incorrect. A user can contact your CGI script without ever going near
your form.

You are allowing your users to call any subroutine in your program.

Paul Lalli
 
A

anno4000

John W. Krahn said:
Fortunately the syntax highlighting in my editor of choice allows me to
distinguish between built-in functions and user defined subroutines.

:)

Ignoring the smiley for the moment, the problem with syntax highlighters
for Perl is that they aren't reliable. They tend to let you down
exactly in the marginal cases when you could use the help.

What's worse, sometimes a quirk in the syntax highlighter makes people
use non-obvious code because the highlighter can't cope with the obvious
solution.

Currently I'm still using vim's syntax highlighting only out of inertia.
One of these days I'm going to switch it off for good.

Anno
 
A

anno4000

In another situation, I find it most useful as well. For example, I
typically determine what to do in a script by checking an incoming
parameter of a form:

my $MODE=param('Mode');
{
no strict;
$MODE="GetLogin" unless $MODE; # default sub to execute
&$MODE; # else execute this sub
}

This saves a lot of 'if-else' chains. Just my 2 Canadian cents.

I don't see how it saves an "if". The "else..." comment is misleading.
You are making sure that $MODE points to a sub, and *then* (not "else")
you're executing it.

That aside, your code doesn't require an ampersand in the call.
"$MODE->()" would work just as well.

Anno
 
P

Paul Lalli

I don't see how it saves an "if". The "else..." comment is
misleading.
You are making sure that $MODE points to a sub, and *then*
(not "else") you're executing it.

I'm assuming he meant it prevents the need for something like:
if ($MODE eq 'Foo') {
Foo();
} elsif ($MODE eq 'Bar') {
Bar();
} else {
GetLogin();
}

Really, he's talking about Symrefs here, which is not at all the same
issue as using an & or not on a subroutine.

Paul Lalli
 
M

Martijn Lievaart

Ignoring the smiley for the moment, the problem with syntax highlighters
for Perl is that they aren't reliable. They tend to let you down
exactly in the marginal cases when you could use the help.

What's worse, sometimes a quirk in the syntax highlighter makes people
use non-obvious code because the highlighter can't cope with the obvious
solution.

Currently I'm still using vim's syntax highlighting only out of inertia.
One of these days I'm going to switch it off for good.

Emacs suffers from much the same problems. F.i. quote like operators are
not properly recognized, making me write:

next if m'^#';

instead of

next if /^#/;

In general I can live with it though.

M4
 
A

anno4000

Paul Lalli said:
I'm assuming he meant it prevents the need for something like:
if ($MODE eq 'Foo') {
Foo();
} elsif ($MODE eq 'Bar') {
Bar();
} else {
GetLogin();
}

Really, he's talking about Symrefs here, which is not at all the same
issue as using an & or not on a subroutine.

Right, that makes sense. It would still be preferable to use a dispatch
table (untested):

my %func = map {
no strict 'refs';
( $_ => \ &{ $_ });
} qw( Foo Bar Baz);

my $mode = param( 'Mode');
( $func{ $mode} || \ &GetLogin)->()

That way the symrefs are restricted to the table setup where they will
only be used with the code-determined qw( Foo Bar Baz). Whatever
value $mode has at run time, only these functions or GetLogin will
be called. The original code could call anything an attacker happens
to know about.

Anno
 
R

Randal L. Schwartz

Martijn> Emacs suffers from much the same problems. F.i. quote like operators are
Martijn> not properly recognized, making me write:

Martijn> next if m'^#';

Martijn> instead of

Martijn> next if /^#/;

Martijn> In general I can live with it though.

That's a flaw with perl-mode. cperl-mode is far better, and actively
maintained. First thing I do with an empty .emacs file is teach it
to replace perl mode with cperl-mode. :)
 
M

Martijn Lievaart

Martijn> Emacs suffers from much the same problems. F.i. quote like
operators are Martijn> not properly recognized, making me write:

Martijn> next if m'^#';

Martijn> instead of

Martijn> next if /^#/;

Martijn> In general I can live with it though.

That's a flaw with perl-mode. cperl-mode is far better, and actively
maintained. First thing I do with an empty .emacs file is teach it to
replace perl mode with cperl-mode. :)

Can you give me the magic incantations? I'm not very fluent in emacs-lisp.

TIA,
M4
 
T

trudge

It's also a rather absurdly large security whole. You have no way of
knowing what that parameter is. You are making the assumption that
the only way to contact your CGI script is via your form. This is
incorrect. A user can contact your CGI script without ever going near
your form.

You are allowing your users to call any subroutine in your program.

Paul Lalli

I see where that would be possible. But would a user not need to know
the name of a subroutine in my script? My goal is to try and combine
as many functions as possible into one script, rather than have 5 or 6
separate scripts to maintain. Which brings up a question: if a user
can call any subroutine in my script, what's to stop them from running
a separate script as well?

If there is no secure way to do this with this particular method I
would like to know so as to fix it.
 
T

trudge

I don't see how it saves an "if". The "else..." comment is misleading.
You are making sure that $MODE points to a sub, and *then* (not "else")
you're executing it.

That aside, your code doesn't require an ampersand in the call.
"$MODE->()" would work just as well.

Anno

You're right - I was a little hasty with my wording. And thanks for
the usage of $MODE sans the leading ampersand.
 
T

trudge

(e-mail address removed) wrote in






The current exchange rate notwithstanding, not worth much, I am afraid.

The proper way to do this allows you to check if an invalid mode was
provided using a lookup table.

# untested code

my %mode_handlers = (
GetLogin => \&GetLogin,
...
);

my $mode = param('Mode');

my $handler;

if ( exists $mode_handlers{ $mode } ) {
$handler = $mode_handlers{ $mode } ;

}

unless ( defined $handler ) {
$handler = $mode_handlers{ GetLogin };

}

$handler->( ... );

__END__

The exists guard is necessary if you are running under mod_perl or
Fast::CGI or any other environment where you program is expected to
serve multiple requests.

Otherwise, each invalid mode request can increase the memory footprint
of your program.

Sinan

Ah, thank you for this suggestion. I will implement this in my
scripts.
--
Amer Neely
Web Mechanic - www.webmechanic.softouch.on.ca
Your sig separator is incorrect: It should be dash-dash-space-newline.
Yours is missing a space.

Fixed now. Thanks.
 
A

anno4000

Lawrence Statton said:
I agree with the solution to that *particular* problem, but as is oft
said: Nothing but perl can parse Perl with absolute certainty. While
cperl-mode does not get nearly as confused nearly as often as
perl-mode did, I have succeeded in confusing its parser on occasion.

That being said, what superior alternative does the grandparent poster
propose? Merely saying that the syntax-highlighter is imperfect does
not obviate the benefits that even a mediocre highlighter offers.

Superiority is relative. For the moment I'm still using the highlighter
that comes with vim though I find some of its properties annoying. The
most significant problem is, as mentioned, the alternative of either
looking at mis-highlighted code or using a style I wouldn't use if
it weren't to appease the highlighter. More generally, I'm not too
fond of the fruit-salad-like appearance of highlighted code in general.
Most of the time I'm just ignoring the colors (and underlines, and
italics, and what have you).

I guess I'll switch to no syntax highlighting per default and enabling
it from case to case when I think it would help, with some key bindings
thrown in to switch quickly. It's a way to use a tool without it getting
in the way, or so I hope.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top