Perl accessing package constant from different package - perl

I'm new to Perl and I'm learning OOP in Perl right now.
Is there a way without any additional libraries (it is forbidden to use any additional lib) to access variable from one package in another one?
package Class;
my $CONSTANT = 'foo'; # this doesn't work, neither our $CONSTANT ..
# ...
# class methodes
# ...
package main;
print Class::$CONSTANT ."\n";

Your constant declaration is wrong
Constants do not have a $ before their name because they are not variables -- a variable (as implied by the name) contains a value which can vary.
Try this (it uses the constant module but that's included in the default installation:
use constant CONSTANT => "Foo";
Accessing class constants
You can then access them as:
Class::CONSTANT # I suggest NOT using this as 'Class::Constant' is a module name, rename your class to something useful
Or, if you have $obj as an instance of Class:
$obj->CONSTANT;
Sample code showing both access methods
use warnings;
use strict;
package MyClass;
use constant SOME_CONSTANT => 'Foo';
sub new
{
my $type = shift; # The package/type name
my $self = {}; # Empty hash
return bless $self, $type;
}
package main;
print MyClass::SOME_CONSTANT . "\n"; # Prints 'Foo\n'
my $obj = MyClass->new();
print $obj->SOME_CONSTANT; # Prints 'Foo'
And a demo.

Easy mistake to make. Put the sigil in front of the class name, e.g.
print ${Class::CONSTANT} . "\n";
print $Class::CONSTANT . "\n";
In addition constants can be defined using the constant package, e.g.
use constant MY_CONSTANT => 5;
print MY_CONSTANT();

You have to define variable using our.
package Class;
our $CONSTANT = 'foo';
# ...
# class methodes
# ...
package main;
print $Class::CONSTANT ."\n";
Keyword package works as syntactic block, so variable defined using my is not accessible outside this syntax block. You also have to place sigil $ in right place. And of course it is variable, not constant.

Related

Perl :: Accessing Members of an Object with `use strict` Set?

I'm a Java/C/C#/python coder who is attempting his first Perl script, and I have what is prob a Perl OOO 101 question: What is the syntax to access an object's members when use strict is required?
Let me speak Java for a moment. I have this little program, all in one class file:
class Dude{
public String name;
public Dude(String name){
this.name = name;
}
public void IntroduceYourself(){
System.out.println("Hi, I'm "+this.name);
}
}
public toy(){
Dude fred = new Dude("Fred");
fred.IntroduceYourself();
}
Output on my Ubuntu machine:
me#ubuntu01:~/$ java toy
Hi, I'm Fred
me#ubuntu01:~/$
What could be simpler? I create a Dude object, then later call method Dude.IntroduceYourself(), which accesses a class member.
Okay: I have to do the exact same thing, but now in Perl (v5.26.1). Again, use strict; is required. Here's my miserable attempt:
#!/usr/bin/perl
use warnings;
use strict;
# Define a "Dude" class
package Dude;
sub new
{
my $class = shift;
my $self = {
_name => shift,
};
bless $self, $class;
return $self;
}
sub IntroduceYourself
{
print("Hi, I'm $object->{name}\n"); # Compilation Error here!
}
my $object = new Dude("Fred");
$object->IntroduceYourself();
Output on the same Ubuntu machine:
me#ubuntu01:~/$ ./toyPerl.pl
Global symbol "$Dude" requires explicit package name (did you forget to declare "my $Dude"?) at ./toyPerl.pl line 18.
Execution of ./toyPerl.pl aborted due to compilation errors.
me#ubuntu01:~/$
Ugh. I've been reading a few Perl tutorials, and I see examples on how to write that IntroduceYourself() subroutine, but none with use strict as a global directive. Can anyone see what I'm doing wrong?
Also: I'm really confused about what I'll call "member functions" in Perl. In my Java example, Dude.IntroduceYourself() was defined as a method of class Dude. I intend (if possible) for IntroduceYourself() to be a function of Object/Class Dude in the Perl code. But its unclear to me how to define that. Am I misunderstanding how Perl objects handle member functions? Thank you.
This doesn't have to do with OO, just Perl's normal strict behavior. strict forces you to declare variables, like in other languages. Without strict, undeclared objects are globals. $object is never declared, so it violates strict.
To solve this, $object must be declared. Perl's this is passed in as the first argument to a method. You need to get that argument. Perl calls this the "invocant". Typically it is called $self.
What is the syntax to access an object's members
Perl doesn't have object members like Java. A Perl object is just a reference. It doesn't even need to be a hash reference. $self->{key} is just using a hash reference, so the key has to match. $self->{_name} not $self->{name}.
sub IntroduceYourself {
# Get the invocant off the list of arguments.
my $self = shift;
# Use it as a hash reference with the correct key.
print("Hi, I'm $self->{_name}\n");
}
I intend (if possible) for IntroduceYourself() to be a function of Object/Class Dude in the Perl code. But its unclear to me how to define that.
You did it. A class is just a package. A method is just a subroutine in a package. The language does not make a distinction between subroutines and methods, nor between class and object methods. It's just how you use them.
#!/usr/bin/perl
use strict;
use warnings;
package Foo {
sub new {
my $class = shift;
my($name) = #_;
return bless { name => $name }, $class;
}
sub hello {
my $self = shift;
print "Hello my name is $self->{name}\n";
}
}
my $foo = Foo->new("Pete");
# Called as an object method.
$foo->hello;
# Called as a subroutine.
# It works, but don't do it; it bypasses inheritance.
Foo::hello($foo);
# Called as a class method.
# It "works", but since the method expects $self to be a
# reference, not a package name, $self->{name} is... it's complicated.
Foo->hello;
Perl's OO is extremely basic. You get classes (via packages), multiple-inheritance (via #ISA), and methods (via subroutines with the invocant passed in) and that's about it. No accessors, no public, no private, no members, not even this.
If you want that, you have to write it yourself, or use an existing library. If you want all the bells and whistles and a full marching band, install Moose.
...use strict as a global directive...
use strict is not global, it is local to the current scope. The current scope is the whole file, but you can put it in a block.
{
# strict is on in this block
use strict;
my $foo = 42;
print "$foo\n";
}
# strict is off everywhere else
$bar = 23;
print "$bar\n";
Things like strict and warnings are referred to as "pragmas".
See "What's the difference between dynamic and lexical (static) scoping? Between local() and my()?".
sub IntroduceYourself {
my $self = shift;
print( "Hi, I'm $self->{ _name }\n" );
}
See perlootut.
In OOP, the invocant (the value of the expression before the ./->) is passed to the method as an argument. In Java, this argument is made available as this. In Perl, this argument is made available as a leading parameter.
This means that
$o->foo( $x, $y )
is equivalent to
my $method = $o->can( 'foo' );
$method->( $o, $x, $y )
And the method looks like this:
sub foo {
my $self = shift;
my $x = shift;
my $y = shift;
$self->{ x } = $x;
$self->{ y } = $y;
}

Perl using a variable to reference a module messes up passing parameters

I have a problem when using a variable to reference a module, it seems to mess up the passing of the variables:
TOTO.pm
package TOTO;
use Data::Dumper;
sub print {
print Dumper(#_);
}
Perl program
package main;
TOTO::print('Hello World');
print ">>>>>>>>>>>\n";
my $package = 'TOTO';
$package->print('Hello World');
And the output is:
$VAR1 = 'Hello World';
>>>>>>>>>>>
$VAR1 = 'TOTO';
$VAR2 = 'Hello World';
Any advice on how to avoid having TOTO passed as the first variable?
Short: The observed behavior comes from use of -> on a package name.
The arrow operator is used with a reference or with an object, which itself is a reference to a data structure that has been bless-ed into its class. (Or with a class name, see below.) That object or the class name is quietly passed as the first argument so that the whole system would work. Note that the package in the question does not define a class (objects cannot be created with it).
From Arrow operator in perlop
"-> " is an infix dereference operator, just as it is in C and C++. If the right side is either a [...] , {...} , or a (...) subscript, then the left side must be either a hard or symbolic reference to an array, a hash, or a subroutine respectively. (Or technically speaking, a location capable of holding a hard reference, if it's an array or hash reference being used for assignment.) See perlreftut and perlref.
It continues, to statements of direct interest in this problem
Otherwise, the right side is a method name or a simple scalar variable containing either the method name or a subroutine reference, and the left side must be either an object (a blessed reference) or a class name (that is, a package name). See perlobj.
So in uses related to classes the left-hand side may contain the class name, and class methods can then be invoked on it (or it can be just queried). Given that a class is a package then this is a package name.
The situation in the question falls within this so the package name is passed to the subroutine. However, according to the above quote it seems that the sub can only be a method, which isn't the case here. So it may be that this use of -> should really be disallowed. Either way, using it on a package which isn't a class strikes me as mistaken.
Update to clarification. This use was intended, to resolve an ambiguity in which package was loaded. The package name is saved into a variable and then the sub invoked on it, using the arrow operator. In this case code would have to be added to the sub to handle the first argument (package name) which is passed regardless of the invocation, by the courtesy of the arrow operator. But then we would have to allow a case when this is invoked on an object, ending up with a code that covers two distinct uses. I believe that it is better to change to a design that does not involve all this.
If you want to use a package, say as a library
File TOTO.pm
pacakge TOTO;
use Exporter;
our (#ISA, #EXPORT_OK);
#ISA = ('Exporter');
#EXPORT_OK = qw(prn); # This can be asked for by user of package
use Data::Dumper;
sub prn {
print Dumper(#_);
}
1; # important for 'require' when this is used
I've changed the sub name to prn so that it's not a Perl library function. The main script
use warnings;
use strict;
use TOTO qw(prn);
prn("Hello World");
The fully qualified name TOTO::prn() can always be used. If you wanted to make this a class that would require a bit more in the package.
This package, TOTO, does not export anything by default, unless asked for. That's what #EXPORT_OK sets up and that's why we need to list functions to import into main:: when use TOTO. Start, for example, with perlmod
In the simplest terms, to create an object-oriented TOTO module you must create a file TOTO.pm that contains at least a constructor subroutine new
package TOTO;
sub new {
bless {};
}
sub print {
print "I am a TOTO object\n";
}
1;
That code must be saved in a file called TOTO.pmthat must match the package TOTO name in the source
Then you may write a program, say main.pl, that uses that module. For instance
use strict;
use warnings 'all';
use TOTO;
my $object = TOTO->new;
$object->print;
And then you have created a new TOTO object that says what it is
If I run
$ perl main.pl
I get the output
I am a TOTO object
You will want to make this code more useful, and there are many variations on this theme, but those are the basics
That's just how Perl's package system works. You need to handle this yourself in the sub being called. You can't change it prior to the call.
sub print {
# special variable __PACKAGE__ contains "TOTO"
if ($_[0] eq __PACKAGE__ || ref $_[0] eq __PACKAGE__){
shift; # throw away class/object
}
print Dumper(#_);
}
The ref $_[0] part isn't technically needed, because you don't have a constructor in your class (you call the method on the class only, but it will just do the right thing if you ever do use objects without having to change anything later).
Here's the issue
Any advice on how to avoid having TOTO passed as the first variable?
You've discovered the answer yourself. This works fine
TOTO::print('Hello World');
If you call it as
TOTO->print('Hello World');
then you're asking for perl to call print as a class method and pass ('TOTO', 'Hello World') as parameters to the TOTO::print subroutine
If TOTO is just a bunch of subroutines then, as you found, just call TOTO::totosub
Check differences between this:
TOTO::print("Hello World");
and
TOTO->print("Hello World");
which is not proper object notation, because TOTO is just a string.
Syntaxe object->function(arguments) whil pass object as 1st argument, to be stored as $this, for sample.
sub print {
my $this = shift #_;
print Dumper(#_);
}
May do the job (even if not blessed object).
Try this:
package TOTO;
use Data::Dumper;
sub new { return bless {}, shift; }
sub print {
my $self = shift #_;
if ( scalar $self =~ /=HASH\(/ ) {
print Dumper(#_);
} else {
print Dumper($self);
}
}
package main;
my $package = TOTO->new();
$package->print("Hello World");
TOTO::print("Hello World");
This could output:
$VAR1 = 'Hello World';
$VAR1 = 'Hello World';
And have a look at man perlobj, man perlootut and man perlmodlib

Trying to localize an outside package variable through a lexical binding in Perl

It's a long title, but I'm afraid I can't take a single word out without losing the true meaning of the question. I'll give a quick description of what I'm trying to achieve first, then a long rambling on why I want it done this way. Skip the rambling if you intend to directly answer abiding with the question title :-)
Quick description
Assuming the existence of a lexicalize builtin that does just what I want, here goes:
package Whatever;
{
lexicalize $Other::Package::var;
local $var = 42;
Other::Package->do_stuff; # depends on that variable internally
}
Whys and whynots
For a bit of context, I'm whitebox-testing a third-party module.
I want the variable localized because I want it changed for a limited time only, before the tests move on to something else. local is the best way I found to do this without depending on knowing the module's choice for an initial value.
I want a lexical binding for two main reasons:
I don't want to pollute the test file's higher-level namespace.
I want something shorter than the fully-qualified name. It's not in the sample code for brevity, but I use the identifier a lot more than what's shown, with calculations and updates relative to its previous value.
I couldn't decently use our because it won't grab a variable from another package: “No package name allowed for variable $Other::Package::var in "our".” Cheating to temporarily enter Other::Package's scope doesn't cut it: if I use a block ({ package Other::Package; our $var }) then the binding doesn't last long enough to be useful; and if I don't (package Other::Package; our #var; package main) then I need to know and copy the previous package's name, which prevents moving that piece of code around too much.
While doing my homework before asking a previous form of this question, I discovered Lexical::Var, which seemed like it would be exactly what I needed. Alas: “Can't localize through a reference.”
I've also tried my best on my gut feeling of my *var-based forms, but kept bumping into syntax errors. I've learned more than I cared to about scoping and binding today :-)
I can't think of a reason why what I want shouldn't be possible, but I can't find the right incantation. Am I asking for an unfortunate unimplemented edge case?
If I get you right, all you need is our. Forgive me if I dont.
Here's working example:
#!/usr/bin/env perl
use strict;
use warnings;
package Some;
our $var = 42;
sub do_stuff { return $var }
package main;
{
local $Some::var = 43;
print "Localized: " . Some->do_stuff() . "\n";
};
print "Normal: " . Some->do_stuff() . "\n";
But if you try to localize private (my) variable of some package, you probably doing something wrong.
there are several ways to do this:
given:
{package Test::Pkg;
our $var = 'init';
sub method {print "Test::Pkg::var = $var\n"}
}
alias a package variable from the current package to the target package.
{
package main;
our $var;
Test::Pkg->method; # Test::Pkg::var = init
local *var = \local $Test::Pkg::var;
# alias $var to a localized $Test::Pkg::var
$var = 'new value';
Test::Pkg->method; # Test::Pkg::var = new value
}
Test::Pkg->method; # Test::Pkg::var = init
localize through a glob reference:
{
package main;
my $var = \*Test::Pkg::var; # globref to target the local
Test::Pkg->method; # Test::Pkg::var = init
local *$var = \'new value'; # fills the scalar slot of the glob
Test::Pkg->method; # Test::Pkg::var = new value
}
Test::Pkg->method; # Test::Pkg::var = init
bind a the lexical in the target package, and let it spill into the current package:
{
package Test::Pkg; # in the target package
our $var; # create the lexical name $var for $Test::Pkg::var
package main; # enter main package, lexical still in scope
Test::Pkg->method; # Test::Pkg::var = init
local $var = 'new value';
Test::Pkg->method; # Test::Pkg::var = new value
}
Test::Pkg->method; # Test::Pkg::var = init
the last example uses a slightly awkward double package declaration to create a lexical in one package and get it into another. This trick is useful with local in other scenarios:
no strict 'refs';
local ${'Some::Pkg::'.$name} = 'something';
use strict 'refs';
I am not quite sure if I understand you correctly. Does this help?
#!/usr/bin/env perl
{
package This;
use warnings; use strict;
our $var = 42;
sub do_stuff {
print "$var\n";
}
}
{
package That;
use warnings; use strict;
use Lexical::Alias;
local $This::var;
alias $This::var, my $var;
$var = 24;
print "$var\n";
This->do_stuff;
}
package main;
use warnings; use strict;
This->do_stuff;
package Other::Package;
$var = 23;
sub say_var {
my $label = shift;
print "$label: $Other::Package::var\n";
}
package Whatever;
Other::Package::say_var("before");
{
local $Other::Package::var = 42;
local *var = \$Other::Package::var;
Other::Package::say_var("during");
print "\$Whatever::var is $var inside the block\n";
}
Other::Package::say_var("after");
print "\$Whatever::var is ",
defined($var) ? "" : "un", "defined outside the block\n";
Output:
before: 23
during: 42
$Whatever::var is 42 inside the block
after: 23
$Whatever::var is undefined outside the block
local $Other::Package::var makes the original value temporarily 42 for the duration of the block, and local *var = \$Other::Package::var makes $var in the current package an alias for $Other::Package::var temporarily for the duration of the block.
Naturally some of this isn't strict-compliant, but I avoided using our because our obfuscates the issue if both packages are in the same file (as they might be if you copy-pasted this sample) — the our declaration can leak out of the package it's used in, into a following package in the same file :)

Perl packages: how to import classes into the 'use'r's namespace?

I'm working on a package that defines exceptions (using Exception::Class::Nested) for its 'parent' package. I don't want the parent package to have to use the really long names, though, and I don't want to pollute any other namespace.
So what I'd like to do is export the last element of the class names into the namespace of the package that used the exception package.
For example, an excerpt from the exception package:
package Klass:Foo::Bar::Exceptions;
use vars qw( #ISA #EXPORT #EXPORT_OK ... );
#ISA = qw( Klass::Foo::Bar Exporter );
use Exception::Class::Nested 0.04 (
'Klass::Foo::Bar::Exceptions::BaseClass' => {
description => 'Base class for exceptions',
'Klass::Foo::Bar::Exceptions::NameError' => {
error => "I don't like your face"
}
}
);
The 'parent' package:
package Klass::Foo::Bar;
use Klass::Foo::Bar::Exceptions;
Klass::Foo::Bar::Exceptions::NameError->throw(error => "D'oh!");
my $e = NameError->new(error => 'Mwahaha!');
I'd like to export/import the exception class such that the second invocation (the my $e one) works as though NameError was defined in Klass::Foo::Bar, but I haven't figured it out yet.
(And before anyone says 'but Exception::Class has the nifty alias thingy,' I'll point out that the alias name is linked specifically to the exception's throw method, so I can't use that for non-auto-thrown new invocations..)
One thing I tried is putting this in the exception package's importer sub (#snames is either an array of the fully-qualified exception classes (e.g., 'Klass::Foo::Bar::Exceptions::NameError'), or just the tail end (e.g., 'NameError'):
my $caller = caller();
$caller ||= 'main';
my #snames = #{$EXPORT_TAGS{exceptions}};
for my $exc (#snames) {
$exc =~ s/^.*:://;
no strict qw(subs refs);
*{"${caller}\:\:${exc}\:\:"} = \*{__PACKAGE__ . "\:\:${exc}\:\:"};
}
But this ends up requiring me to invoke the exceptions using Klass::Foo::Bar::NameError rather than just NameError. It seems it works, but too well.
I don't want to import NameError into main::!
Typeglobs and symbol tables are still a bit mysterious to me, I'm afraid.
I'm sure there's a way to do what I want (or else I'm doing something that I shouldn't altogether, but let's leave that alone for now). Can anyone help me with this?
Thanks!
In your example import sub, you are aliasing package stashes, which is not going to do what you want. Instead, you want to create subroutines with the shortened names that return the full package name:
sub import {
my $caller = caller;
for my $long (#{$EXPORT_TAGS{exceptions}}) { # for each full name
my ($short) = $long =~ /([^:]+)$/; # grab the last segment
no strict 'refs';
*{"$caller\::$short"} = sub () {$long}; # install a subroutine named
# $short into the caller's pkg
# that returns $long
}
}
Breaking apart that last line, sub () {$long} creates an anonymous subroutine that takes no arguments. The code reference contains the single variable $long which retains the value it had during the loop iteration. This is called a lexical closure, which basically means that the subroutine's compilation environment ($long and it's value) will persist as long as the subroutine does.
This anonymous subroutine is then installed into the caller's package with the $short name. The fully qualified name of a subroutine in the caller's package is caller::subname, which "$caller\::$short" constructs. This is then dereferenced as a typeglob *{ ... }. Assignment to a typeglob with a reference fills that slot of the typeglob. So assigning a code reference installs the subroutine.
Put another way, the following subroutine declaration:
sub short () {'a::long::name'}
means the same thing as:
BEGIN {*{__PACKAGE__.'::short'} = sub () {'a::long::name'}}

How can I use a variable as a module name in Perl?

I know it is possible to use a variable as a variable name for package variables in Perl. I would like to use the contents of a variable as a module name. For instance:
package Foo;
our #names =("blah1", "blah2");
1;
And in another file I want to be able be able to set the contents of a scalar to "foo" and then access the names array in Foo through that scalar.
my $packageName = "Foo";
Essentially I want to do something along the lines of:
#{$packageName}::names; #This obviously doesn't work.
I know I can use
my $names = eval '$'. $packageName . "::names"
But only if Foo::names is a scalar. Is there another way to do this without the eval statement?
To get at package variables in package $package, you can use symbolic references:
no strict 'refs';
my $package = 'Foo';
# grab #Foo::names
my #names = #{ $package . '::names' }
A better way, which avoids symbolic references, is to expose a method within Foo that will return the array. This works because the method invocation operator (->) can take a string as the invocant.
package Foo;
our #names = ( ... );
sub get_names {
return #names;
}
package main;
use strict;
my $package = 'Foo';
my #names = $package->get_names;
Strict checking is preventing you from using a variable (or literal string) as part of a name, but this can be disabled locally:
my #values;
{
no strict 'refs';
#values = #{"Mypackage"}::var;
}