2011-07-06 6 views
8

In Perl, v'è mai alcuna differenza tra i seguenti due costrutti:In Perl, c'è qualche differenza tra l'aliasing globale di glob e l'aliasing tramite lo stash?

*main::foo = *main::bar 

e

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

Essi sembrano avere la stessa funzione (aliasing tutti gli slot in *main::foo a quelle definite nella *main::bar), ma mi chiedo solo se questa equivalenza è sempre valida.

+3

Sono curioso di cosa ha portato questo. :) –

+1

Il primo causa un errore quando è abilitato il rigoroso 'subs' o strict, quest'ultimo è permesso. – MkV

+1

Stavo scrivendo un ciclo per creare alias alcuni nomi di metodi e ho iniziato a chiedermi perché scrivo sempre '{no strict 'refs'; * {'some :: pkg'. $ new} = * {'some :: pkg'. $ old} 'quando' $ some :: pkg :: {$ new} = $ some :: pkg :: {$ old } 'funzionerebbe altrettanto bene. Intuitivamente sembrano uguali, ma cose come legature/sovraccarichi/altre magie potrebbero avere conseguenze "interessanti" se gestiscono la copia in modo diverso, sia come bug che come comportamento previsto. –

risposta

9

Forse non è il tipo di differenza che stavate cercando, ma ci sono due grandi differenze tra *main::foo e $main::{foo}; il primo ricerca il glob nella memoria in fase di compilazione, creandolo se necessario, mentre il secondo cerca il glob nella memoria in fase di esecuzione e non lo crea.

Questo potrebbe fare la differenza per qualsiasi altra cosa che riguarda la memoria, e sicuramente può influire sull'avviso used only once.

+0

Per persone come me che non sono in Perl esoterics: [Stashes and Globs] (http://www.perlmonks.org/?node=perlguts#Stashes_and_Globs): "* Una scorta è un hash che contiene tutti i diversi oggetti che sono contenuti in un pacchetto: ogni chiave dello stash è un nome di simbolo (condiviso da tutti i diversi tipi di oggetti che hanno lo stesso nome) e ogni valore nella tabella hash è un GV (Glob Value). turn contiene riferimenti ai vari oggetti di quel nome * "... la corsa Perl non finisce mai! –

+0

@DavidTonhofer soprattutto perché non è abbastanza preciso; in alcuni casi la scorta può avere valori che non sono GV. – ysth

3

Il seguente 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"; 

Uscite:

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()'" 

Quindi, se *main::foo = *main::bar; non fa la stessa cosa che $main::{foo} = $main::{bar};, io sono in perdita su come rilevare un pratico differenza. ;) Tuttavia, dal punto di vista della sintassi, potrebbero esserci situazioni in cui è più semplice utilizzare un metodo rispetto ad un altro. ... si applicano sempre i soliti avvertimenti su come muoversi nella tabella dei simboli.

+0

la mia ipotesi è che qualsiasi differenza (se ce n'è una) sarebbe in qualche magia esoterica o un algoritmo di memorizzazione nella cache troppo zelante.sintatticamente ci sono differenze sostanziali, il codice da assegnazione globale accoppiato con 'no strict 'refs'' in una routine' import' è un po' più breve (e più veloce) che separare manualmente il chiamante e camminare la tabella dei simboli livello per livello, che mi porta a preferire la sintassi glob, ma quando si scrive con un nome completo conosciuto in anticipo (o già elaborando una scorta per qualche altra ragione), la differenza sintattica è un po 'più oscura, quindi la domanda :) –

+1

Guardare sotto il cofano è una divertente diversione. Penso che ci siano situazioni in cui la buona notazione del vecchio glob è la più chiara, mentre ci sono altre situazioni in cui la notazione $ namespace :: {key} è più chiara. Qualunque sia più chiaro per un particolare bisogno, questo è il modo di farlo. :) Ovviamente se una persona può trovare un'alternativa al guado attraverso la tabella dei simboli ci sono molte ragioni per evitare l'approccio del design. – DavidO

3

Accesso alla scorta come $A::{foo} = $obj consente di posizionare nulla sul tabella dei simboli, mentre *A::foo = $obj luoghi $obj sullo slot atteso del typeglob in base al tipo di $obj.

Ad esempio:

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 '([email protected], $!, $^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 
Problemi correlati