2011-02-01 9 views
16

W this question plakat zapytał, jak wykonać następujące czynności w jednym wierszu:Demystifying glob Perl (*)

sub my_sub { 
    my $ref_array = shift; 
    my @array = @$ref_array; 
} 

który z mojej wiedzy podstawowej magii Perl chciałbym uniknąć po prostu za coś takiego:

sub my_sub { 
    my $ref_array = shift; 
    for (@$ref_array) { 
     #do somthing with $_ here 
    }; 

    #use $ref_array->[$element] here 
} 

jednak w jednym z lokalnych this answer mnichów So tchrist zasugerował:

sub my_sub { 
    local *array = shift(); 
    #use @array here 
} 

Kiedy zapytałem

Próbując dowiedzieć się średniego szczebla Perl magię, mogę zapytać, co to jest, że ustawiania do czego tutaj? Czy ustawiasz odwołanie do @array na , które zostało przekazane? Jak wiesz, że tworzysz @array i nie% array lub $ array? Gdzie mogę dowiedzieć się więcej o tym * operatora (perlop?). Dzięki!

Zasugerowałem, aby zadać to pytanie jako nowy post, choć dał on dobre referencje. W każdym razie, tutaj idzie? Czy ktoś może wyjaśnić, co jest przypisane do tego, co i jak powstaje @array, zamiast być może% tablica lub tablica $? Dzięki.

+0

Prawdopodobnie można zdobyć kilka ważnych informacji na temat typeglobów z [tej odpowiedzi] (http://stackoverflow.com/questions/3807231/how-can-i-test-if-i-can-write-toa-a- filehandle/4200474 # 4200474), z których żaden nie został tu jeszcze dotknięty. – tchrist

Odpowiedz

21

Przyporządkowanie do glob

*glob = VALUE 

zawiera magiczne, który zależy od rodzaju VALUE (to jest, wartości powrotnej, na przykład, Scalar::Util::reftype(VALUE)). Jeśli VALUE jest odniesieniem do skalaru, tablicy, hasza lub podprocedury, to wpis w tabeli symboli zostanie nadpisany.

idiom ten

local *array = shift(); 
#use @array here 

działa jako udokumentowane gdy pierwszy argument podprogram referencja tablicy. Jeśli zamiast tego podano pierwszy argument, powiedzmy, odniesienie skalarne, to zadanie będzie miało wpływ tylko na $array, a nie na @array.

Trochę skrypt demo, aby zobaczyć, co się dzieje:

no strict; 

sub F { 
    local *array = shift; 

    print "\@array = @array\n"; 
    print "\$array = $array\n"; 
    print "\%array = ",%array,"\n"; 
    print "------------------\n"; 
} 

$array = "original scalar"; 
%array = ("original" => "hash"); 
@array = ("orignal","array"); 

$foo = "foo"; 
@foo = ("foo","bar"); 
%foo = ("FOO" => "foo"); 

F ["new","array"];  # array reference 
F \"new scalar";   # scalar reference 
F {"new" => "hash"};  # hash reference 
F *foo;     # typeglob 
F 'foo';     # not a reference, but name of assigned variable 
F 'something else';  # not a reference 
F();      # undef 

wyjściowa:

 
@array = new array 
$array = original scalar 
%array = originalhash 
------------------ 
@array = orignal array 
$array = new scalar 
%array = originalhash 
------------------ 
@array = orignal array 
$array = original scalar 
%array = newhash 
------------------ 
@array = foo bar 
$array = foo 
%array = FOOfoo 
------------------ 
@array = foo bar 
$array = foo 
%array = FOOfoo 
------------------ 
@array = 
$array = 
%array = 
------------------ 
@array = orignal array 
$array = original scalar 
%array = originalhash 
------------------ 

dodatkowe doc na perlmod i perldata.W czasach poprzedzających odniesienia były częścią Perla, ten idiom był pomocny w przekazywaniu tablic i skrótów do podprogramów.

+1

dlaczego nie rządzisz już? – hobbs

+0

Nie zapominaj, co się stanie, gdy RHS do przypisania typeglob nie będzie ani typeglobem, ani referencją, ale łańcuchem. Zastanów się także, co stanie się, gdy operand znaku '*' jest ciągiem, a nie bossem. Na koniec rozważ "local". – tchrist

+0

Jak pokazuje ta odpowiedź, przypisanie do globu wypełnia różne miejsca w zależności od typu odniesienia. Możesz zwięźle upewnić się, że masz właściwy typ, taki jak: 'local * array = \ @ {shift @_}'. Para odniesień/dereferencji '\ @' jest przezroczysta, jeśli ref jest tablicą, ale w przeciwnym razie spowoduje błąd. –

3

Z moją, co prawda, mniejszą niż czarodziejką wiedzą o Perlu, zaryzykuję odpowiedź. Operator * przypisuje wpis tablicy symboli. Jak rozumiem, @array,% array i $ array all odnoszą się do tego samego wpisu tablicy symboli dla łańcucha 'array', ale do różnych pól w tym wpisie: pola ARRAY, HASH i SCALAR. Tak więc przypisanie local *array = shift; faktycznie przypisuje cały lokalny wpis tablicy symboli dla "tablicy" (w tym pola ARRAY, HASH i SCALAR) do tego, co zostało przekazane, użytemu w wywołującym.

+1

Jeśli rzeczą przypisaną jest glob lub globref, tak; w przeciwnym razie jest to bardziej skomplikowane. W rzeczywistości jest to i tak bardziej skomplikowane, ponieważ wpis w tablicy symboli jest jak "zmienna globalna", która zawiera "wartość globalną", a przypisanie ustawia część wartości, a nie samą zmienną. – ysth

Powiązane problemy