Kiedy powinienem użyć & do wywołania podprogramu Perla?

Słyszałem, że ludzie nie powinni używać & do wywoływania subów Perla, czyli:

function($a,$b,...);
# opposed to
&function($a,$b,...);

Wiem, że po pierwsze lista argumentów staje się opcjonalna, ale jakie są przypadki, w których właściwe jest użycie & i przypadki, w których absolutnie nie powinieneś jej używać?

Również w jaki sposób performace increase wchodzi w grę, pomijając &?

Author: brian d foy, 2009-08-28

4 answers

IMO, jedynym powodem użycia & jest uzyskanie lub wywołanie coderef, np.:

sub foo() {
    print "hi\n";
}

my $x = \&foo;
&$x();

Główny czas, w którym Możesz użyć go, którego absolutnie nie powinieneś w większości przypadków, to wywołanie suba, które ma prototyp, który określa dowolne niestandardowe zachowanie wywołania. Chodzi mi o to, że niektóre prototypy umożliwiają reinterpretację listy argumentów, na przykład konwersję specyfikacji @array i %hash Na odwołania. Więc sub będzie oczekiwać tych reinterpretacji, które miały miejsce, i o ile nie przejdziesz do wszelkich niezbędnych długości, aby naśladować je ręcznie, sub otrzyma wejścia szalenie różne od tych, których oczekuje.

Myślę, że głównie ludzie próbują ci powiedzieć, że nadal piszesz w stylu Perl 4, a teraz mamy dużo czystszą, ładniejszą rzecz o nazwie Perl 5.

Jeśli chodzi o wydajność, istnieją różne sposoby, w jakie Perl optymalizuje wywołania podrzędne, które & pokonuje, z których jednym z głównych jest inlining stałych.

Istnieje również jedna okoliczność, w której użycie & zapewnia korzyści wydajnościowe: jeśli przekierowujesz wywołanie podrzędne za pomocą foo(@_). Użycie &foo jest nieskończenie szybsze niż foo(@_). Nie polecałbym tego, chyba że definitywnie stwierdzisz, profilując, że potrzebujesz tej mikro-optymalizacji.

 33
Author: chaos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-13 16:27:13

Jestem częstym oprawcą &, ale głównie dlatego, że robię dziwne rzeczy z interfejsem. Jeśli nie potrzebujesz żadnej z tych sytuacji, nie używaj &. Większość z nich jest po prostu po to, aby uzyskać dostęp do definicji podprogramu, a nie wywołać podprogramu. Wszystko jest w perlsub.

  1. Biorąc odniesienie do nazwanego podprogramu. Jest to prawdopodobnie jedyna wspólna sytuacja dla większości Perlerów: {]}

     my $sub = \&foo;
    
  2. Podobnie, przypisanie do typeglob, który pozwala na wywołanie podprogram o innej nazwie:

     *bar = \&foo;
    
  3. Sprawdzanie, czy podprogram jest zdefiniowany, jak można w zestawach testowych:

     if( defined &foo ) { ... }
    
  4. Usunięcie definicji podprogramu, która nie powinna być powszechna:

     undef &foo;
    
  5. Zapewnienie podprogramu dyspozytora, którego jedynym zadaniem jest wybranie odpowiedniego podprogramu do wywołania. Jest to jedyna sytuacja, w której używam & do wywołania podprogramu, a kiedy spodziewam się zadzwonić do dyspozytora wiele, wiele razy i muszę wycisnąć trochę wydajności z operacji:

     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
  6. Aby przeskoczyć do innego podprogramu używając bieżącego stosu argumentów (i zastępując bieżący podprogram w stosie wywołań), operacja unrare w dispatchingu, szczególnie w AUTOLOAD:

     goto ⊂
    
  7. Wywołaj podprogram, który nazwałeś po wbudowanym perlu. & zawsze daje Ci zdefiniowaną przez użytkownika. To jest dlaczego uczymy go w Uczenie Się Perla. Nie chcesz tego robić. to normalnie, ale to jedna z cech &.

Są miejsca, gdzie można je wykorzystać, ale są lepsze sposoby: {]}

  1. Wywołanie podprogramu o tej samej nazwie, co Wbudowany Perl. Po prostu nie mają podprogramów o tej samej nazwie, co Wbudowany Perl. Sprawdź perlfunc , aby zobaczyć listę wbudowanych nazw, których nie powinieneś używać.

  2. Aby wyłączyć prototypy. Jeśli nie wiesz, co to oznacza lub dlaczego chcesz, nie użyj &. Jakiś kod czarnej magii może go potrzebować, ale w takich przypadkach prawdopodobnie wiesz, co robisz.

  3. Do dereferencji i wykonania referencji podprogramu. Wystarczy użyć notacji ->.

 50
Author: brian d foy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-28 00:44:20

Forma &podprogram() wyłącza sprawdzanie prototypu. To może być to, czego chcesz.

Http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

Prototypy pozwalają określić liczby i typy argumentów podprogramu i sprawdzać je podczas kompilacji. Może to zapewnić użyteczną pomoc diagnostyczną.

Prototypy nie mają zastosowania do wywołań metod lub wywołań wykonanych w starym stylu przy użyciu prefiksu&.

The & is niezbędne do odniesienia się do podprogramu lub odniesienia do kodu

Np.

sub foo {
   # a subroutine
}

my $subref = \&foo; # take a reference to the subroutine

&$subref(@args);  # make a subroutine call using the reference.

my $anon_func = sub { ... }; # anonymous code reference
&$anon_func(); # called like this

Protypy również nie mają zastosowania do podprogramów.

Forma & podprogramu jest również używana w tak zwanej formie magic goto.

Wyrażenie goto &subroutine zastępuje bieżący kontekst wywołania wywołaniem nazwanej podprogramu, używając bieżącej wartości @_.

Zasadniczo, można całkowicie przełączyć wywołanie na jeden podprogram z wywołaniem na wywołanie nazwane. Jest to powszechnie widoczne w blokach AUTOLOAD, gdzie można wykonać odroczone wywołanie podprogramu, być może z pewną modyfikacją@_, ale wygląda to całkowicie tak, jakby było to wywołanie do nazwanego sub.

Np.

sub AUTOLOAD {
    ...
    push @_, @extra_args; # add more arguments onto the parameter list
    goto &subroutine ; # change call another subroutine, as if we were never here
}

}

Potencjalnie może to być przydatne do eliminacji wywołania ogonowego , jak sądzę.

Zobacz szczegółowe wyjaśnienie tej techniki tutaj

 16
Author: cms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-05 14:36:12

Czytałem argumenty przeciwko używaniu '&', ale prawie zawsze go używam. Oszczędza mi to zbyt dużo czasu, żeby tego nie zrobić. Spędzam bardzo dużą część mojego czasu kodowania Perla, szukając części kodu, które wywołują określoną funkcję. Z wiodącym&, mogę wyszukiwać i znajdować je natychmiast. Bez wiodącego &, dostaję definicję funkcji, komentarze i instrukcje debugowania, Zwykle potrajając ilość kodu, który muszę sprawdzić, aby znaleźć to, czego szukam.

Najważniejsze, że nie używasz '&' you is pozwala na korzystanie z prototypów funkcji. Prototypy funkcji Perla mogą jednak tworzyć błędy tak często, jak im zapobiegają, ponieważ pobierają listę argumentów i reinterpretują ją w sposób, którego nie można się spodziewać, tak że wywołanie funkcji nie przekazuje argumentów, które dosłownie mówi.

 1
Author: Phil Goetz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 03:35:10