2 votes

Que se passe-t-il si vous appelez shift à l'intérieur d'un sub anonyme ?

Tout d'abord, je vous prie de m'excuser si cette question est mal posée ; en fait, je ne connais pas grand-chose au langage Perl.

J'essaie de déboguer un code existant qui est censé envoyer les notes de notre système de devoirs en ligne appelé WeBWorK à un LMS. Je rencontre une erreur bizarre où je pense que quelque chose n'est pas initialisé correctement, ou peut-être que ce n'est pas la bonne classe. Je pense que le problème pourrait se situer ici :

sub go {
    my $self = shift;
    my $r = $self->r;
    my $ce = $r->ce;

    # If grades are begin passed back to the lti then we peroidically
    # update all of the grades because things can get out of sync if
    # instructors add or modify sets.
    if ($ce->{LTIGradeMode}) {

      my $grader = WeBWorK::Authen::LTIAdvanced::SubmitGrade->new($r);

      my $post_connection_action = sub {
        my $grader = shift;

        # catch exceptions generated during the sending process
        my $result_message = eval { $grader->mass_update() };
        if ($@) {
          # add the die message to the result message
          $result_message .= "An error occurred while trying to update grades via LTI.\n"
        . "The error message is:\n\n$@\n\n";
          # and also write it to the apache log
          $r->log->error("An error occurred while trying to update grades via LTI: $@\n");
        }
      };
      if (MP2) {
        $r->connection->pool->cleanup_register($post_connection_action, $grader);
      } else {
        $r->post_connection($post_connection_action, $grader);
      }
    }
... # a bunch of other stuff happens in the "go" sub

Je pense que le problème se situe au niveau des $grader variable ; en particulier, je ne sais pas ce que les my $grader = shift; fait à l'intérieur d'un sous-marin anonyme. Par exemple, si la sous-section avait un nom, il serait plus clair que shift donne le premier argument passé au sub. Mais comme c'est anonyme, je ne sais pas ce qu'il pense être ses arguments.

De plus, je ne sais pas vraiment pourquoi cette ligne est nécessaire. D'après mes recherches sur Internet, j'ai cru comprendre que le but d'un sous-programme anonyme est de garder toutes les variables de l'environnement dans le champ d'application. Alors pourquoi avons-nous besoin de redéfinir $grader à l'intérieur du sous-marin anonyme en premier lieu ?

Merci d'avoir aidé un noob perl ! :)

4voto

ikegami Points 133140

Les abonnés anonymes n'ont rien de spécial à cet égard.

my $cr = sub {
   my $arg = shift;
   say $arg;
};

$cr->("foo");   # Prints "foo"
$cr->("bar");   # Prints "bar"

Dans votre cas, vous passez $post_connection_action y $grader a cleanup_register o post_connection dans l'espoir qu'il aboutisse à un appel à l'adresse suivante &$post_connection_action con $grader comme premier argument. Le fait que cette attente soit correcte ou non dépend de l'implémentation de la fonction cleanup_register y post_connection dont je ne sais rien.


Notez qu'une autre solution se présente ici. Les sous-sous ont accès aux lexiques qui étaient dans le champ d'application lorsque la fonction sub a été évalué.

my $prefix = "> ";
my $cr = sub {
   my $arg = shift;
   say "$prefix$arg";   # Captures $prefix from sub{} scope.
};

$cr->("foo");           # Prints "> foo"

Ce qui précède est vrai même si les lexiques capturés n'existeraient plus au moment où le sous est appelé.

my $cr;
{
   my $prefix = "> ";
   $cr = sub {
      my $arg = shift;
      say "$prefix$arg";   # Captures $prefix from sub{} scope.
   };
}                          # $prefix would normally stop existing here.

$cr->("foo");              # Prints "> foo"

Cela signifie que vous n'avez pas besoin de passer $grader comme argument. Il peut simplement être capturé . Laissez tomber my $grader = shift; (et ne passez pas $grader à cleanup_register o post_connection ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X