Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Need help with constants and package names.

Reply
Thread Tools

Need help with constants and package names.

 
 
Terry
Guest
Posts: n/a
 
      12-12-2004
Hello all, I'm having trouble with packages and constants. What I'd
like to have is a single .pm for all constants used by the application.
The application will have other .pm files as well, and I'd like for them
to have access to the constants as well. I thought the following would
do what I want, but fails miserably:

#### file: ./main
#!/usr/bin/perl

use warnings;
use strict;

use One::Two::Constants;
use One::Two::Obj;

print "Constant PI is: " , PI , "\n";
my $obj = Obj->new();
print "Object member PI is: " , $obj->{'pi'} , "\n";




#### file ./One/Two/Constants.pm
package One::Two::Constants;

use constant { PI => 3.1415 };

1;



#### file ./One/Two/Obj.pm
package One::Two::Obj;

use warnings;
use strict;

use One::Two::Constants;

sub new {
my $class = shift;
my $self = {
some => 'thing' ,
more => 'stuff' ,
pi => PI
};
return bless $self , $class;
}

1;


$ ./main
Bareword "PI" not allowed while "strict subs" in use at One/Two/Obj.pm
line 10.
Compilation failed in require at ./main line 7.
BEGIN failed--compilation aborted at ./main line 7.



The only way I've been able to get this to run is by removing the
package declaration from Constants.pm, changing the package declaration
of Obj.pm to just 'package Obj', and by referring to 'PI' inside of
Obj.pm as 'main:I'. Clearly this is a poor approach.

All I want is all constants kept in one place, able to be referred to
from anywhere else. Any suggestions?

As a side note, aren't package names supposed to be fully qualified?
i.e, aren't .pm file supposed to begin with something like:

package One::Two::Something;

Importing with 'use' only seems to work when packages are declared with
only their basename:

package Something;

Thank you for your help.

-Terry
 
Reply With Quote
 
 
 
 
John Bokma
Guest
Posts: n/a
 
      12-12-2004
Terry wrote:

> All I want is all constants kept in one place, able to be referred to
> from anywhere else. Any suggestions?


Just don't do it that way, try to use namespaces (packages), e.g

Math:I

etc.

--
John Small Perl scripts: http://johnbokma.com/perl/
Perl programmer available: http://castleamber.com/
Happy Customers: http://castleamber.com/testimonials.html

 
Reply With Quote
 
 
 
 
Sherm Pendley
Guest
Posts: n/a
 
      12-12-2004
Terry wrote:

> Hello all, I'm having trouble with packages and constants. What I'd
> like to have is a single .pm for all constants used by the application.
> The application will have other .pm files as well, and I'd like for them
> to have access to the constants as well. I thought the following would
> do what I want, but fails miserably:


.... snip ...

> #### file ./One/Two/Constants.pm
> package One::Two::Constants;
>
> use constant { PI => 3.1415 };
>
> 1;


Long answer, read:

perldoc Exporter
perldoc perlmod
perldoc perlmodlib

Short answer, to export symbols into the caller's package, inherit from
Exporter and declare them in @EXPORT:

package One::Two::Constants;

use strict;
use warnings;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(PI);

use constant PI => 3.1415;

1;

But *do* read the long answer. The code above is enough to get you
started, but there's definitely a lot more to learn than this simple
example shows.

> As a side note, aren't package names supposed to be fully qualified?
> i.e, aren't .pm file supposed to begin with something like:
>
> package One::Two::Something;


That is correct.

> Importing with 'use' only seems to work when packages are declared with
> only their basename:
>
> package Something;


No, use works just fine with nested module names. If it's not working
for you, post a short (but complete) script that demonstrates the problem.

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      12-12-2004
Terry <(E-Mail Removed)> wrote in news:ca8pr0pkrtso5n6o2lanlnhscmc2mqlgk0@
4ax.com:

> Hello all, I'm having trouble with packages and constants.


In addition to Sherm and John's excellent responses, let me just point
out that you can save yourself a lot of trouble by using h2xs. While its
official description states:

DESCRIPTION
*h2xs* builds a Perl extension from C header files. The extension
will include functions which can be used to retrieve the value of
any #define statement which was in the C header files.

it can also be used to generate nice skeleton files for your modules.

h2xs -AXn One::Two::Constants

See

perldoc h2xs

for more information.

Sinan

--
A. Sinan Unur
http://www.velocityreviews.com/forums/(E-Mail Removed)d
(remove '.invalid' and reverse each component for email address)

 
Reply With Quote
 
Terry
Guest
Posts: n/a
 
      12-12-2004
On Sun, 12 Dec 2004 15:20:03 -0500, Sherm Pendley <(E-Mail Removed)>
wrote:

>Long answer, read:
>
>perldoc Exporter
>perldoc perlmod
>perldoc perlmodlib


Thanks for the lead! After reading the Exporter perldoc I see my
blunder.

>Short answer, to export symbols into the caller's package, inherit from
>Exporter and declare them in @EXPORT:
>
>package One::Two::Constants;
>
>use strict;
>use warnings;
>
>use Exporter;
>our @ISA = qw(Exporter);
>our @EXPORT = qw(PI);
>
>use constant PI => 3.1415;
>
>1;



Something I didn't find in the perldoc was how to export a hash using
the 'use constant' pragma. The examples seemed to be geared toward
single imports as in your example. The reason I'm using 'use export'
with a hash ref is to import multiple constants (I'll have at least
fifty by the time I'm done). ie:

use constant {
one => 1 ,
two => 2 ,
# ...
};

How then to pass this list to @EXPORT ? I tried assigning the hash ref
to a scalar first and assigning its keys into @ISA , but you probably
already know that didn't work Any suggestions?



>> As a side note, aren't package names supposed to be fully qualified?
>> i.e, aren't .pm file supposed to begin with something like:
>>
>> package One::Two::Something;

>
>That is correct.
>
>> Importing with 'use' only seems to work when packages are declared with
>> only their basename:
>>
>> package Something;

>
>No, use works just fine with nested module names. If it's not working
>for you, post a short (but complete) script that demonstrates the problem.
>


The Obj.pm file in my last post demonstrates the problem:


##### file: ./One/Two/Obj.pm
package One::Two::Obj;

use warnings;
use strict;

use One::Two::Constants;

sub new {
my $class = shift;
my $self = {
some => 'thing' ,
more => 'stuff' ,
pi => PI
};
return bless $self , $class;
}

1;

###### file ./main
#!/usr/bin/perl

use warnings;
use strict;

use One::Two::Constants;
use One::Two::Obj;

my $obj = Obj->new();



$ ./main
Can't locate object method "new" via package "Obj" (perhaps you forgot
to load "Obj"?) at ./main line 10.

If I change the package declaration in Obj.pm from 'One::Two::Obj' to
just 'Obj' it works fine. I also tried exporting 'new' from Obj.pm as
in your example above to no avail.

>sherm--


Thanks again for your help Sherm!

 
Reply With Quote
 
Christopher Nehren
Guest
Posts: n/a
 
      12-12-2004
On 2004-12-12, A. Sinan Unur scribbled these
curious markings:
> In addition to Sherm and John's excellent responses, let me just point
> out that you can save yourself a lot of trouble by using h2xs. While its
> official description states:

[...]
> See
>
> perldoc h2xs


In further addition, I'd like to suggest Module::Starter (and its
command-line frontend, module-starter) as a modern alternative /
complement to h2xs. It presents a friendlier interface to module
skeleton creation, and isn't historically (read: confusingly, for the
new user anyway) named.

You can find M::S on your local CPAN mirror.

Best Regards,
Christopher Nehren
--
I abhor a system designed for the "user", if that word is a coded
pejorative meaning "stupid and unsophisticated". -- Ken Thompson
If you ask the wrong questions, you get answers like "42" and "God".
Unix is user friendly. However, it isn't idiot friendly.
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      12-12-2004
Christopher Nehren <(E-Mail Removed)> wrote in
news:(E-Mail Removed) s.org:

> In further addition, I'd like to suggest Module::Starter (and its
> command-line frontend, module-starter) as a modern alternative /
> complement to h2xs.


I did not know about this module. Thanks very much.

Sinan.

--
A. Sinan Unur
(E-Mail Removed)d
(remove '.invalid' and reverse each component for email address)

 
Reply With Quote
 
Sherm Pendley
Guest
Posts: n/a
 
      12-12-2004
Terry wrote:

> Something I didn't find in the perldoc was how to export a hash using
> the 'use constant' pragma. The examples seemed to be geared toward
> single imports as in your example. The reason I'm using 'use export'
> with a hash ref is to import multiple constants (I'll have at least
> fifty by the time I'm done). ie:
>
> use constant {
> one => 1 ,
> two => 2 ,
> # ...
> };
>
> How then to pass this list to @EXPORT ? I tried assigning the hash ref
> to a scalar first and assigning its keys into @ISA , but you probably
> already know that didn't work Any suggestions?


I haven't found a way to do that either - and believe me I've tried. In
my CamelBones project I have one file with over a hundred constants -
each one appears twice, once to define its value and once in @EXPORT.

> The Obj.pm file in my last post demonstrates the problem:
>
> ##### file: ./One/Two/Obj.pm
> package One::Two::Obj;
>
> use warnings;
> use strict;
>
> use One::Two::Constants;
>
> sub new {


.... snip ...

> ###### file ./main
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use One::Two::Constants;
> use One::Two::Obj;
>
> my $obj = Obj->new();
>
>
> $ ./main
> Can't locate object method "new" via package "Obj" (perhaps you forgot
> to load "Obj"?) at ./main line 10.


To call a class method like new(), you need to specify the full class
name, not just the last component of it:

my $obj = One::Two::Obj->new();

Objects know what package they belong to though, so instance methods can
be called with the name of the method alone:

$obj->do_something();

> If I change the package declaration in Obj.pm from 'One::Two::Obj' to
> just 'Obj' it works fine.


In that case, you're not using Exporter in One::Two::Obj. If you were,
it wouldn't work as expected because the file name doesn't match the
package name.

use One::Two::Obj;

is roughly equivalent to

BEGIN {
require "One/Two/Obj.pm";
One::Two::Obj::import();
}

But if the code in One/Two/Obj.pm is actually in package Obj, there
would be no One::Two::Obj::import() to call. So the symbols in the
module wouldn't be correctly imported into the calling package.

> I also tried exporting 'new' from Obj.pm as


You only need to export non-oo functions. Class methods are normally
called using the fully-qualified class name as above. Instance methods
are called via an object reference, and the class of the object is used
to determine the package to find the method in.

sherm--

--
Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
 
Reply With Quote
 
Terry
Guest
Posts: n/a
 
      12-13-2004
On Sun, 12 Dec 2004 17:24:16 -0500, Sherm Pendley <(E-Mail Removed)>
wrote:

>I haven't found a way to do that either - and believe me I've tried. In
>my CamelBones project I have one file with over a hundred constants -
>each one appears twice, once to define its value and once in @EXPORT.


Thanks anyway. I looked at your CamelBones project too - very
interesting!

>To call a class method like new(), you need to specify the full class
>name, not just the last component of it:
>
>my $obj = One::Two::Obj->new();


Ah, got it. I was expecting it to be Java-ish, where after the package
is imported, it can be instantiated via its class name only.

Thanks again for the help Sherm.

-Terry
 
Reply With Quote
 
Terry
Guest
Posts: n/a
 
      12-13-2004
On 12 Dec 2004 21:40:32 GMT, "A. Sinan Unur" <(E-Mail Removed)>
wrote:

>Christopher Nehren <(E-Mail Removed)> wrote in
>news:(E-Mail Removed) ns.org:
>
>> In further addition, I'd like to suggest Module::Starter (and its
>> command-line frontend, module-starter) as a modern alternative /
>> complement to h2xs.

>
>I did not know about this module. Thanks very much.
>
>Sinan.


Thanks for the help on this thread! I'm working with a refactor of some
existing code, but I'll remember this the next time I need to create a
module.

-Terry

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Constants across package boundaries bernie@fantasyfarm.com Perl Misc 15 05-14-2008 08:20 PM
Retrieve package constants Agoston Bejo ASP General 0 09-01-2004 09:45 AM
Importing a package and looping through modules in the package Dave Python 2 02-10-2004 08:14 PM
need help with runtime constants El Durango Java 3 02-09-2004 08:50 AM
Accessing constants from another package/file. ed Perl Misc 3 06-26-2003 01:24 AM



Advertisments