How to avoid subroutine redefined warning & Strict ref problem

How to avoid subroutine redefined warning & Strict ref problem

am 06.02.2008 11:05:18 von Mark Knoop

Hi

I am not sure if these two problems are related or not. I am new to writing
class moodules.

I have a class which I use to store a load of values when calling a CGI app.
One of them is the url which I get using the url function from CGI and then
store in my global class. It makes sense to me to call it url even though
this clashes with the CGI function. This has been working fine but I have
now added a getter method to my globals module and it has broken it in two
ways.

The following code recreates the error.

Example.pm
#########################
package Example;

use strict;
use warnings;

use CGI qw(:cgi);

sub new {

my $class = shift;

my $self = {};

$self->{url} = url(-path_info=>1);

bless ($self, $class);

return $self;

}

sub url {

my $self = shift;

return $self->{url};

}

1;
##############################

example.pl
###############################
use strict;
use warnings;

use Example;

my $ex = Example->new;

print $ex->url;

Expected output:

This should print the url which run in this example on my laptop defaults to
http://localhost and works if I take out the use strict and warnings.

Actual output:

With use strict and warnings though I get

Subroutine url redefined at Example.pm line 22.
Can't use string ("-path_info") as a HASH ref while "strict refs" in use at
Exam
ple.pm line 26.

Is there some clever namespace thing I can do to avoid the first warning
without renameing my method?

Any idea on what is causing the second error message?

Thanks
Mark

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

RE: How to avoid subroutine redefined warning & Strict ref problem

am 06.02.2008 11:43:18 von Brian Raven

Mark Knoop <> wrote:
> Hi
> =

> I am not sure if these two problems are related or not. I am new to
> writing class moodules. =

> =

> I have a class which I use to store a load of values when calling a
> CGI app. =

> One of them is the url which I get using the url function from CGI
> and then store in my global class. It makes sense to me to call it
> url even though this clashes with the CGI function. This has been
> working fine but I have now added a getter method to my globals
> module and it has broken it in two ways. =

> =

> The following code recreates the error.
> =

> Example.pm
> #########################
> package Example;
> =

> use strict;
> use warnings;
> =

> use CGI qw(:cgi);

This imports a number of CGI names into your package namespace,
including url. If you want to call your subroutine url then you can't
import the CGI sub of the same name. So, remove the "qw(:cgi)".

> =

> sub new {
> =

> my $class =3D shift;
> =

> my $self =3D {};
> =

> $self->{url} =3D url(-path_info=3D>1);

As the CGI::url sub is no longer imported into this namespace you will
have to fully qualify that call, e.g.

$self->{url} =3D CGI::url(-path_info=3D>1);

or possibly using a CGI object

my $cgi =3D CGI->new;
$self->{url} =3D $cgi->url(-path_info=3D>1);

> =

> bless ($self, $class);
> =

> return $self;
> =

> }
> =

> sub url {
> =

> my $self =3D shift;
> =

> return $self->{url};
> =

> }
> =

> 1;
> ##############################
> =

> example.pl
> ###############################
> use strict;
> use warnings;
> =

> use Example;
> =

> my $ex =3D Example->new;
> =

> print $ex->url;
> =

> Expected output:
> =

> This should print the url which run in this example on my laptop
> defaults to http://localhost and works if I take out the use strict
> and warnings. =

> =

> Actual output:
> =

> With use strict and warnings though I get
> =

> Subroutine url redefined at Example.pm line 22.
> Can't use string ("-path_info") as a HASH ref while "strict refs" in
> use at Exam ple.pm line 26. =

> =

> Is there some clever namespace thing I can do to avoid the first
> warning without renameing my method? =


Yes, see above. Depending on what you are trying to do, you might also
consider inheriting from CGI.

> =

> Any idea on what is causing the second error message?

As the first warning says, the sub has been redefined. The first clue is
the line number which is in your url sub. More specifically, the line
"return $self->{url};", which attempts a hash dereference ("->{}") of
the first parameter (the string "-path_info"), which isn't a hash
reference. That is, the url call in your new sub is calling your url
sub, not the CGI one.

HTH

-- =

Brian Raven =


==================== =====3D=
================
Atos Euronext Market Solutions Disclaimer
==================== =====3D=
================

The information contained in this e-mail is confidential and solely for the=
intended addressee(s). Unauthorised reproduction, disclosure, modification=
, and/or distribution of this email may be unlawful.
If you have received this email in error, please notify the sender immediat=
ely and delete it from your system. The views expressed in this message do =
not necessarily reflect those of Atos Euronext Market Solutions.

Atos Euronext Market Solutions Limited - Registered in England & Wales with=
registration no. 3962327. Registered office address at 25 Bank Street Lon=
don E14 5NQ United Kingdom. =

Atos Euronext Market Solutions SAS - Registered in France with registration=
no. 425 100 294. Registered office address at 6/8 Boulevard Haussmann 750=
09 Paris France.

L'information contenue dans cet e-mail est confidentielle et uniquement des=
tinee a la (aux) personnes a laquelle (auxquelle(s)) elle est adressee. Tou=
te copie, publication ou diffusion de cet email est interdite. Si cet e-mai=
l vous parvient par erreur, nous vous prions de bien vouloir prevenir l'exp=
editeur immediatement et d'effacer le e-mail et annexes jointes de votre sy=
steme. Le contenu de ce message electronique ne represente pas necessaireme=
nt la position ou le point de vue d'Atos Euronext Market Solutions.
Atos Euronext Market Solutions Limited Soci=E9t=E9 de droit anglais, enregi=
str=E9e au Royaume Uni sous le num=E9ro 3962327, dont le si=E8ge social se =
situe 25 Bank Street E14 5NQ Londres Royaume Uni.

Atos Euronext Market Solutions SAS, soci=E9t=E9 par actions simplifi=E9e, e=
nregistr=E9 au registre dui commerce et des soci=E9t=E9s sous le num=E9ro 4=
25 100 294 RCS Paris et dont le si=E8ge social se situe 6/8 Boulevard Hauss=
mann 75009 Paris France.
==================== =====3D=
================

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: How to avoid subroutine redefined warning & Strict ref problem

am 06.02.2008 14:41:18 von Ingo Schwarze

Hi Mark,

> use CGI qw(:cgi);

I consider that bad style.
At the very least, such code is hardly maintainable.
Imagine someone else reads this code.
It's very hard to guess which symbols get imported.
In the case at hand, not even the man page tells you:

:cgi
Import all CGI-handling methods, such as param(), path_info()
and the like.

Statement like "and the like" im manpages make me shudder.
So, you force the reader of you code to read the source using
things like "locate CGI.pm" and "less CGI.pm".
That's bad for three reasons:
1) They have to rely on undocumented interfaces.
2) Being forced to consult library sources to understand
application code will considerably slow down maintenance
and development.
3) In the particular case at hand, qw(:cgi) is incredibly messy:

':cgi' => [ qw/
param upload path_info path_translated url self_url script_name
cookie Dump raw_cookie request_method query_string Accept user_agent
remote_host content_type remote_addr referer server_name
server_software server_port server_protocol virtual_port
virtual_host remote_ident auth_type http append save_parameters
restore_parameters param_fetch remote_user user_name header redirect
import_names put Delete Delete_all url_param cgi_error
/ ],

You want to tell me that you will never use method names like
"append", "redirect", "put" and "Delete" in your class?
Sorry, i don't believe you.
You want to tell me that you want to check this list for clashes
whenever you choose a new method name in your class?
That doesn't sound quite credible, either.

Never use global imports.
At least, you should say something like

use CGI qw(url);

to be explicit.

> sub url {

No way.
You cannot have two different objects with the same name in the same scope.
Being unique (per scope) is what names are all about...

Either, choose a different name for your own method.

Or, even better, rewrite your code like so:

require CGI;
# [...]
sub new {
# [....]
$self->{url} = CGI::url( -path_info => 1 );

> Subroutine url redefined at Example.pm line 22.

That's the name clash.
The use-statement implies "Example::url = CGI::url".
Later, you say "Example::url = sub {...}".

> Can't use string ("-path_info") as a HASH ref while "strict refs" in use
> at Example.pm line 26.

Well, the function "url" getting called in new() is your own.
So you get

my $self = "-path_info";
return "-path_info"->{url}; # BOOM.

Good luck,
Ingo

--
Ingo Schwarze | Software Engineer | Framework Team
Astaro AG | www.astaro.com | 76227 Karlsruhe | Germany
_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs