In Perl, is there any difference between direct glob aliasing and aliasing via the stash?
Asked Answered
M

4

9

In Perl, is there ever any difference between the following two constructs:

*main::foo = *main::bar

and

$main::{foo} = $main::{bar}

They appear to have the same function (aliasing all of the slots in *main::foo to those defined in *main::bar), but I am just wondering if this equivalency always holds.

Mackinnon answered 6/7, 2011 at 21:36 Comment(6)
I'm curious what brought this up. :)Seduction
The former causes an error when strict 'subs' or strict is enabled, the latter is allowed.Logogriph
I was writing a loop to alias a few method names together and started wondering why I always write {no strict 'refs'; *{'some::pkg'.$new} = *{'some::pkg'.$old} when $some::pkg::{$new} = $some::pkg::{$old} would work just as well. Intuitively they seem the same, but things like ties/overloads/other magic could have "interesting" consequences if they handled the copy differently, either as a bug or an intended behavior.Mackinnon
@Logogriph => the example in my question works fine under strict. a fully qualified identifier is exempt from strictures. the example in my comment above requires turning off strict refs due to the symbolic dereference, but has nothing to do with the glob itself.Mackinnon
Yeah, thinko. I was thinking the difference between *foo = *bar and $::{foo} = $::{bar} when the current package is 'main'.Logogriph
@Logogriph => That example is fine under strict as well, I am not sure what you are getting at.Mackinnon
P
9

Maybe not the kind of difference you were looking for, but there are two big differences between *main::foo and $main::{foo}; the former looks up the glob in the stash at compile time, creating it if necessary, while the latter looks for the glob in the stash at run time, and won't create it.

This may make a difference to anything else poking about in the stash, and it certainly can affect whether you get a used only once warning.

Peterson answered 7/7, 2011 at 3:56 Comment(2)
For people like me who are not into Perl esoterics: Stashes and Globs : "A stash is a hash that contains all of the different objects that are contained within a package. Each key of the stash is a symbol name (shared by all the different types of objects that have the same name), and each value in the hash table is a GV (Glob Value). This GV in turn contains references to the various objects of that name" ... the Perl ride never ends!Upheaval
@DavidTonhofer especially since that isn't quite accurate; in some cases the stash may have values that aren't GVs.Peterson
N
3

The following script:

#!/usr/bin/env perl

#mytest.pl

no warnings;


$bar = "this";
@bar = qw/ 1 2 3 4 5 /;
%bar = qw/ key value /;

open bar, '<', 'mytest.pl' or die $!;

sub bar {
    return "Sub defined as 'bar()'";
}
$main::{foo} = $main::{bar};

print "The scalar \$foo holds $foo\n";
print "The array \@foo holds @foo\n";
print "The hash \%foo holds ", %foo, "\n";
my $line = <foo>;
print "The filehandle 'foo' is reads ", $line;
print 'The function foo() replies "', foo(), "\"\n";

Outputs:

The scalar $foo holds this
The array @foo holds 1 2 3 4 5
The hash %foo holds keyvalue
The filehandle 'foo' is reads #!/usr/bin/env perl
The function foo() replies "Sub defined as 'bar()'"

So if *main::foo = *main::bar; doesn't do the same thing as $main::{foo} = $main::{bar};, I'm at a loss as to how to detect a practical difference. ;) However, from a syntax perspective, there may be situations where it's easier to use one method versus another. ...the usual warnings about mucking around in the symbol table always apply.

Nominee answered 6/7, 2011 at 23:45 Comment(2)
my guess is that any difference (if there is one) would be in some esoteric magic or an overzealous caching algorithm. syntactically there are definitely differences, the code from glob assignment coupled with no strict 'refs' in an import routine is quite a bit shorter (and faster) than manually taking the caller apart and walking the symbol table level by level, which leads me to prefer the glob syntax, but when writing to a fully qualified name known in advance (or already processing a stash for some other reason), the syntactic difference is a bit murkier, hence the question :)Mackinnon
Looking under the hood is a fun diversion. I think that there are situations where the good old glob notation is the clearest, while there are other situations where the $namespace::{key} notation is clearer. Whichever one is clearer for a particular need, that's the way to do it. :) Of course if a person can find an alternative to wading through the symbol table there are a lot of reasons to avoid either approach by design.Nominee
S
3

Accessing the stash as $A::{foo} = $obj allows you to place anything on the symbol table while *A::foo = $obj places $obj on the expected slot of the typeglob according to $obj type.

For example:

  DB<1> $ST::{foo} = [1,2,3]

  DB<2> *ST::bar = [1,2,3]

  DB<3> x @ST::foo
Cannot convert a reference to ARRAY to typeglob at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2.
 at (eval 7)[/usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl:646] line 2
    eval '($@, $!, $^E, $,, $/, $\\, $^W) = @saved;package main; $^D = $^D | $DB::db_stop;
  @ST::foo;

;' called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 646
    DB::eval called at /usr/local/perl/blead-debug/lib/5.15.0/perl5db.pl line 3442
    DB::DB called at -e line 1
  DB<4> x @ST::bar
0  1
1  2
2  3
  DB<5> x \%ST::
0  HASH(0x1d55810)
   'bar' => *ST::bar
   'foo' => ARRAY(0x1923e30)
      0  1
      1  2
      2  3
Spermatozoon answered 7/7, 2011 at 0:57 Comment(0)
T
0

See also "Scalars vs globs (*{} should not return FAKE globs)"

https://github.com/perl/perl5/issues/10625

Tome answered 22/12, 2019 at 12:22 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changesKraal

© 2022 - 2024 — McMap. All rights reserved.