Alternative to use vars

H

Himal

I am using
use vars qw ($scalar @array %hash);
in my program. I would like to know how to declare this in an
alternative way using our and EXPORT. I am not able to grasp what the
reference says about it.

Cheers,
Himal.
 
G

Greg Bacon

: I am using
: use vars qw ($scalar @array %hash);
: in my program. I would like to know how to declare this in an
: alternative way using our and EXPORT. I am not able to grasp what the
: reference says about it.

If you don't want to use the vars pragma, you could fully qualify
your values as in

$pkg::scalar = 3;
@pkg::array = qw/ apples oranges bananas /;
%pkg::hash = ();

where 'pkg' is the name of the package you want your variables to call
home. If you want the main package, you can abbreviate to $::scalar,
for example.

You can also declare the globals with our:

our $scalar;
our @array;
our %hash;

See the perlfunc documentation on our for details.

Hope this helps,
Greg
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

(e-mail address removed) (Greg Bacon) wrote in @corp.supernews.com:
You can also declare the globals with our:

our $scalar;
our @array;
our %hash;

See the perlfunc documentation on our for details.

Maybe I'm dense.... I have yet to grasp the advantage of 'our' over 'use
vars'.

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwP472PeouIeTNHoEQIMhgCaA0q8GLANqUmBONt927YCbybDYpcAnjWA
lPjLquQFXdiUHQFscjdsle4i
=jZKd
-----END PGP SIGNATURE-----
 
T

Tassilo v. Parseval

Also sprach Eric J. Roode:
(e-mail address removed) (Greg Bacon) wrote in @corp.supernews.com:


Maybe I'm dense.... I have yet to grasp the advantage of 'our' over 'use
vars'.

You are not the only one trying to grasp that. The concept of lexically
scoped global (that is, dynamic) variables truely escapes me. The only
advantage I see is that you can introduce new global variables
everywhere easily like so:

our $var;
....
....
our $another_var;

Of course, 'use vars' can also be used multiple times. It's just a
little more to type.

Tassilo
 
T

Tassilo v. Parseval

Also sprach Martien Verbruggen:
On 3 Jul 2003 10:33:08 GMT,


You can limit (with our) where that global variable is accessible:

Yes, and this feels pretty unnatural to me. It remotely reminds me of
the strange scoping that PHP has...where you have to put a global()
before a variable if you want to use it in a particular function:

$var = "var";

function func() {
global $var;
print "var: $var\n";
}

I agree it's even more perverted in PHP because a block there can't
simply access variables that exists in the scope above.
#!/usr/local/bin/perl
use strict;
use warnings;

{
use vars qw/$var/;
$var = "var";
our $our = "our";

print "var: $var\n";
print "our: $our\n";
}

print "var: $var\n";
# print "our: $our\n"; # impossible
sub_needing_global();

sub sub_needing_global
{
our $our;
print "our: $our\n";
} [...]
In a single file, the same effect can be achieved with C<my>, but in
multi-file projects that require a shared global, you can't use C<my>
for the same purpose.

I don't think the above program could be rewritten with lexicals. Any
lexical declared in the upper bare block is lost once the block is left.
Many people would say that it's better to avoid globals alltogether,
but sometimes globals can make life a lot easier, and code much
cleaner. In those cases, our is much preferable over C<use vars>
because of the more finegrained control it gives you about the
accessibility of that variable. It can prevent accidental access of
globals in the same way that C<my> lexical scoping does.

And this is unlikely: You never really have many globals. Secondly, good
style demands that those global variables have a name that distinguishes
them from lexicals (like all uppercased). The danger of an accidental
access is therefore much lower than with lexicals of which you usually
have quite a bunch.
C<use vars> is still deprecated, so it's probably better (unless you
have to write code for 5.005) to not use it anymore.

I was lately busy making Perl5.00503 (the one that comes with FreeBSD 4.7)
work with the current autoconf package. It required a more recent
File::Copy module. I took this module from a 5.8.0 release and of
course, because of our(), it didn't work out of the box. It was easy to
fix because the finer grain of control that our() offers wasn't used.
And this seems to be the whole point: I haven't yet found any code in
the wild that made use of it. Usually it's used as a drop-in replacement
for 'use vars' with the exact same semantics.

I am really fearing the moment when 'use vars' will trigger a deprecated
warning in one of the future Perl5 releases. This will be the point
where you have to start to package-qualify all globals if you want to
write a module which is backwards compatible to at least 5.005.

Tassilo
 
M

Martien Verbruggen

Also sprach Martien Verbruggen:


Yes, and this feels pretty unnatural to me. It remotely reminds me of
the strange scoping that PHP has...where you have to put a global()
before a variable if you want to use it in a particular function:

It doesn't feel unnatural to me. But I guess that's a matter of
personal preference :)

[snip of program]
[...]
In a single file, the same effect can be achieved with C<my>, but in
multi-file projects that require a shared global, you can't use C<my>
for the same purpose.

I don't think the above program could be rewritten with lexicals. Any
lexical declared in the upper bare block is lost once the block is left.

I meant that if you declare a my() variable at file scope, it'd be
available through the whole file, acting a bit as a global, but not
actually being a global. I agree that my wording did not at all
express what I meant :)
And this is unlikely: You never really have many globals. Secondly, good
style demands that those global variables have a name that distinguishes
them from lexicals (like all uppercased). The danger of an accidental
access is therefore much lower than with lexicals of which you usually
have quite a bunch.

And, indeed, when I write brand new code, that's more or less the
strategy I follow. However, sometimes one needs to work with old
code, that was written by people who didn't understand the value of
limiting scope. Rather than rewriting the whole thing to have a clean
base, it's often easier just to accept what's there, and to add the
new functionality required, but this time trying to keep it clean. We
all know that next week we will have a chance to rewrite it to our
liking :)

Martien
 
B

Bart Lateur

Martien said:
You can limit (with our) where that global variable is accessible:

The part that makes no sense to me, is how use of these var now crosses
package boundaries...

$Bar::x = 123;
package Foo;
our $x = "abc";
package Bar;
print $x;

Guess what that'll print?
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Also sprach Eric J. Roode:


You are not the only one trying to grasp that.

Oh good, I'm glad I'm not the only one :)

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPwVpNmPeouIeTNHoEQJ6IQCfcwah2/v88iJeVY4dBWyVwQ3U19IAnjLb
I14yeyTv7IGNWZSHaQ20cvAb
=Le5p
-----END PGP SIGNATURE-----
 
P

Paul van Eldijk

The part that makes no sense to me, is how use of these var now crosses
package boundaries...

$Bar::x = 123;
package Foo;
our $x = "abc";
package Bar;
print $x;

Guess what that'll print?

However, if you change it to
$Bar::x = 123;
package Foo;
use vars qw($x);
$x = "abc";
package Bar;
print $x;

you get the expected result. I guess I´m confued too....


Paul
 
M

Martien Verbruggen

[note that this is strict-safe]

It'll print whatever is in the second $x, because that's where the scope
of that $x extends to. While this is also an effect of C<our>, I don't
like this bit of it. I (very rarely) use our to control the scope of a
global in the other direction, but I've never used it to extend the
scope like this.
However, if you change it to
$Bar::x = 123;
package Foo;
use vars qw($x);
$x = "abc";
package Bar;
print $x;

[note that this is not strict-safe]
you get the expected result. I guess I´m confued too....

This is what the difference between C<our> and C<use vars> is. C<our>
works on lexical scopes, and C<use vars> works on package scope.

C<our> and C<use vars> do not work in the same way. However, for almost
all of the cases of C<use vars> I have ever seen [1], C<our> can be used
instead. In fact, I don't think that there is any strict-safe historical
code, where C<use vars> cannot be simply replaced with C<our>. I can
think of many non-strict safe examples, like the above, but that's
unlikely to ever occur in real code, since C<use vars> wouldn't have
been needed without C<use strict 'vars'>.

So, unless someone can come up with an example with C<use strict> and
C<use vars>, that behaves differently when C<use vars> is replaced with
C<our>, I'd say that C<our> does a good job at replacing C<use vars>, as
it was used, and adds some new scoping rules, that shouldn't present you
with any surprises in code that used to work.

The only time you'll get surprises is in the case of the above-quoted
code example, which requires strictures to not be in force in the
historical version. C<use vars> was always intended to be used with
C<use strict 'vars'> in place, because it circumvents one of the
requirements that C<use strict 'vars'> imposes.

Martien

[1] All cases in real code. The cases that I've seen where a straight
replacement does not work are all in postings to Usenet.
 
M

Michele Dondi

This is what the difference between C<our> and C<use vars> is. C<our>
works on lexical scopes, and C<use vars> works on package scope.

Hmmm... this seems to be the main issue here. Maybe for a future Perl5
release a (backwards compatible) mechanism might be devised, by means
e.g. of a C<package> modifier, that gives a package an implicit
lexical scope.


Michele
 
M

Martien Verbruggen

Hmmm... this seems to be the main issue here. Maybe for a future Perl5
release a (backwards compatible) mechanism might be devised, by means
e.g. of a C<package> modifier, that gives a package an implicit
lexical scope.

You can't do that. Not without major change.

Packages can appear in multiple lexical scopes, and even in multiple
files, simply by using the package keyword.

$ cat Foo.pm
package Foo;
use vars qw/$bar/;
$bar = 3;
1;

$ cat foo.pl
#!/usr/local/bin/perl
use warnings;
use strict;

use Foo;

print "main: $Foo::bar\n";
$Foo::bar = 5;

package Foo;
print "$bar\n";

$ ./foo.pl
main: 3
5

Yes, this is a pathological case, but so are all the cases presented in
this argument. The problem of confusion simply doesn't exist in most of
the code out there.

I tend to think that C<our> is a much better solution than C<use vars>,
because of things like this. There is nothing in foo.pl that indicates
that $bar can be used unqualified. If there had been a C<use vars
'$bar'> in that file in the main package, that would have been very
confusing.

If you need a lexical scope that is different from your file, you use a
block.

Martien
 
M

Michele Dondi

You can't do that. Not without major change.

Well, while I agree on *everything* you said hereafter, I have a doubt
I didn't express myself clearly. Of course my idea is in any case
highly speculative and may well be a very bad one indeed...

What I was thinking of is a "modifier"[1] that applied to a package
creates an "implicit pair of curly brackets, {}" around "all the stuff
in that package. Suppose to call it "private"[2]; then the following
portions of code would be equivalent:

# portion 1
private package mypackage;
....

# portion 2
{
package my package;
...
}

At this point you may argue that writing a pair of curly brackets is
easier than writing a keyword of a bunch of charachters. But as you
know far better than me, a package can be a very long and complex
beast and the use of "my" modifier might have some sense in such
cases.


[1] I hope it is the correct technical term.
[2] I'm aware it's awful: hopefully a better name could be devised.


Just my 2 Eurocents,
Michele
 
M

Martien Verbruggen

You can't do that. Not without major change.

Well, while I agree on *everything* you said hereafter, I have a doubt
I didn't express myself clearly. Of course my idea is in any case
highly speculative and may well be a very bad one indeed...

What I was thinking of is a "modifier"[1] that applied to a package
creates an "implicit pair of curly brackets, {}" around "all the stuff
in that package. Suppose to call it "private"[2]; then the following
portions of code would be equivalent:

# portion 1
private package mypackage;
...

# portion 2
{
package my package;
...
}

At this point you may argue that writing a pair of curly brackets is
easier than writing a keyword of a bunch of charachters. But as you
know far better than me, a package can be a very long and complex
beast and the use of "my" modifier might have some sense in such
cases.

[It may be that I'm still misunderstanding what you're trying to say. If
so, my apologies in advance...]

I would indeed argue that if you want that scope (and that's of course a
lexical scope) that it would be better to use implicit curlies. What I
wanted to emphasise though, is that such a scope, with the curlies, is
different from package scope. A package can exist in more than one
lexical scope, and in fact often exist in more than one file. Package
scope covers all of those lexical scopes. On the other hand, a lexical
scope can also be larger than a package scope. If a variable is declared
with my or our at the top of a file, and that file contains more than
one package, the scope of that variable extends across the packages.

The long and short of it is that package scope and lexical scope are
orthogonal things. They do often overlap in real code, but behind the
scenes there is no real overlap.


From what you write, I wonder whether you mean that you'd like to have a
"lexical" scope that would automatically spring to life when one is in a
certain package. If so, then you're really talking about package scope,
and you're looking for what C<use vars> does, I think. Allowing a real
lexical scope[1] to extend like that would be, IMO, contrary to what a
lexical scope is.

In my view, the current state is quite the way it should be: If you need
a package wide variable, use one. Name it by its fully qualified name,
or use C<our> to lexically scope its short name[2]. If you need a
lexical variable, create one with C<my>. If you need what C<use vars>
does currently, explicitly mention the variable in each lexical scope
you need it with C<our>.

Alternatively, simply type C<no strict> and free yourself from the
shackles :). In my opinion, all of the above, including the deprecation
of C<use vars> lead to better coding practices, and easier to maintain,
less bug-prone code. For me, that's a good reason to support it.

Martien

[1] One that would work with C<our> and C<my> scoped variables...

[2] I would only do that to limit its scope, not to extend it beyond the
package. When a variable is only needed once or twice, I use its full
name.
 
M

Michele Dondi

[It may be that I'm still misunderstanding what you're trying to say. If
so, my apologies in advance...]

This is indeed possible, since english is not my native language and
*my* english is far from perfect. However, still being relatively a
newbie, this conversation is in any case useful for me.

BTW: since you're so kind commenting my article, I'd like to hear your
(and other's) opinion about the other post I wrote, namely the one
about how naturally C<our> fits the existing scheme for "local"
variables under the "natural-language-like-features-in-Perl point of
view"...
I would indeed argue that if you want that scope (and that's of course a
lexical scope) that it would be better to use implicit curlies. What I
wanted to emphasise though, is that such a scope, with the curlies, is
different from package scope. A package can exist in more than one

OK, I see the point *now*. So I might say at most that my
(hypotetical) "solution" is a "first-order approximation" to package
scope (with C said:
The long and short of it is that package scope and lexical scope are
orthogonal things. They do often overlap in real code, but behind the
scenes there is no real overlap.

Perfectly clear. So I guess there's no *simple* way, as I naively
thought, to "link" them together by means of an "esoteric common
vector", at least in Perl5. I wonder if in Perl6 they will actually be
different aspects of the same underlying mechanism (I suppose that for
backward compatibility the same apparent behaviour will be
maintainded).
From what you write, I wonder whether you mean that you'd like to have a
"lexical" scope that would automatically spring to life when one is in a
certain package. If so, then you're really talking about package scope,

This is (more or less) what I meant...
and you're looking for what C<use vars> does, I think. Allowing a real
lexical scope[1] to extend like that would be, IMO, contrary to what a
lexical scope is.

Hmmm, I think I understand now. Thank you for the other detailed
explanations, that I snipped.


Michele
 
M

Martien Verbruggen

BTW: since you're so kind commenting my article, I'd like to hear your
(and other's) opinion about the other post I wrote, namely the one
about how naturally C<our> fits the existing scheme for "local"
variables under the "natural-language-like-features-in-Perl point of
view"...

Is that the one with Message-ID
<[email protected]>?

I read that article earlier, but I wasn't sure whether there was anythin
in there that I could comment on :)

I do think it might show that there is still a bit of a misunderstanding
about what C<my()>, C<local()>, C<our()> and C<use vars> do, and that's
understandable, since they seem to do many similar things.

Maybe a few more explanations, as I see things, could help, in addition
to MJD's "Coping with scoping" article. I'll say much of the same, but
phrased differently.


Perl has two types of variables: There are those that belong to a
package, and those who don't. The ones that don't belong to a package
are _created_ with C<my()>; all others belong to a package. The ones
that don't belong to a package are only available inside of the lexical
scope they are defined in, the others are available globally, which is
why they are also often called global variables.

Perl has two types of scope: lexical scope and "package scope", where
the latter isn't really a scope, more a namespace. Lexical scope is
(mainly) a compile time thing, and is defined by the enclosing block or
file [1]. Package scope is defined by the use of the package keyword.

Variables that don't belong to a package, i.e. the ones created with
c<my()>, are often called lexical variables. This is fine, but it does
introduce a bit of a confusion factor. The term lexical doesn't really
apply to the variable, but only to its name. The name temporary or local
variable would have been a better name[2], since these variables also
cease to exist at the end of the current scope. However, Perl already
had local (see later).

Because lexical scope refers to the name of the variable, and not the
variable itself you can have a lexically scoped package variable with
C<our()>. The variable itself always exists and is accessible, it's just
its short name that is only available in the current lexical scope. It's
as if there is a temporary lexical variable that is an alias for the
package variable[3].

The C<use vars> pragma simply allows you to refer to the named variables
by their short name while inside of the package name space (scope, if
you want).

All of the above work on variable names. Before the days of lexical
variables the mechanism to localise variables was with C<local()>.
However, C<local()> does not really localise a variable, but it
localises a (package) variable value. The current value of the variable
is saved, and restored at the end of the current scope. C<local()> has
no effect on variable names. Nowadays, C<local()> has its main use in
providing temporary values for the builtin variables, and is probably
not the right solution for most other uses.

So, summarising...

C<my()> creates a new non-package variable with lexical scope, and
existence.
C<local()> saves the current value of a package (global) variable and
restores it on leaving the current scope.
C<our()> allows access to a package variable by its short name in the
current lexical scope
C<use vars> allows a variable to be referred to by its short name inside
a package name space.

One of these works with non-package variables, the other three with
globals. Three of these work with (lexical) scopes, and one with package
name spaces. Three of these act on variable names, and one on values
only.
Perfectly clear. So I guess there's no *simple* way, as I naively
thought, to "link" them together by means of an "esoteric common
vector", at least in Perl5. I wonder if in Perl6 they will actually be
different aspects of the same underlying mechanism (I suppose that for
backward compatibility the same apparent behaviour will be
maintainded).

I haven't kept up with Perl 6 too well, but from what I understand a lot
of this is one of the areas where some work will be done.

Perl 6 will depart in many ways from the way things are done in Perl 5.
There is no backward compatibility, except for a Perl5 to Perl 6
translation, which will probably be automatic [4]. Perl 6 is a new language,
and one of the goals of the project is to finally get rid of all the
accumulated backward compatibility mess. Localisation and scope is
actually not that messy, compared to many other things that are being
cleaned up.

Martien

[1] It actually is defined by the location of the declaration up to the
end of the enclosing block or file.

[2] The term private variables, which is also expressed by C<my()> just
doesn't entirely cut it for me, mainly because that expression is
already in heavy use in OO, with a different sort of meaning.

[3] I don't know whether that is how Perl implements it, which is why I
say "as if".

[4] As I said, I don't know too much about it, since I haven't been
following the mailing lists very closely. I just browse them now and
again.
 
M

Michele Dondi

Is that the one with Message-ID
<[email protected]>?

Yes, it is.
I read that article earlier, but I wasn't sure whether there was anythin
in there that I could comment on :)
Fine!

I do think it might show that there is still a bit of a misunderstanding
about what C<my()>, C<local()>, C<our()> and C<use vars> do, and that's
understandable, since they seem to do many similar things.

Maybe a few more explanations, as I see things, could help, in addition
to MJD's "Coping with scoping" article. I'll say much of the same, but
phrased differently.
[snip]

REPETITA IUVANT...
translation, which will probably be automatic [4]. Perl 6 is a new language,
and one of the goals of the project is to finally get rid of all the
accumulated backward compatibility mess. Localisation and scope is

I see... actually, even if Perl is supposed to be a non-elegant (but
magic!) language, whenever I discover *how* an extension to a previous
release and in particular to Perl4 has been added, I'm astonished by
how elegantly such an extension has been implemented wrt backwards
compatibility.


Michele
 
G

Greg Bacon

: In article <[email protected]>,
:
: >Another point that I wanted to discuss yesterday, but avoided to for
: >various reasons, has to do with the well known
: >natural-language-like-features-in-Perl issue: I read MJD's article on
: >Perl's two mechanisms for local variables. I agree that they are
:
: What MJD article, ie, you know its title, maybe
: even the url?

Maybe "Seven Useful Uses of local"?

http://perl.plover.com/local.html

Greg
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top