7 votes

Débogage dans les appels de fonction

Je veux savoir si, dans ce code,

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink;
say might-sink;

le premier appel à might-sink en contexte de l'évier appelle effectivement List.sink c'est-à-dire qu'il ne fait rien. Mon intuition est qu'il le fait, mais je ne suis pas sûr si c'est le cas ou si ce n'est tout simplement pas le cas. réifié de sorte que l'échec n'est signalé que plus tard. J'ai essayé la méthode options de débogage ici mais aucun d'entre eux n'entre dans le code appelé par celui-ci. Donc deux questions, séparées mais liées :

  1. Comment puis-je déboguer dans ces fonctions en utilisant le débogueur Perl 6 ou un module ?
  2. Comment puis-je savoir si cette List.sink est effectivement appelé ou, en général, si sink est appelé lorsqu'un objet se retrouve dans un contexte d'évier ?

6voto

Même si vous avez explicitement appelé .sink sur cette valeur de retour, le Failure n'exploserait pas :

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink.sink;
say "Did not explode";
# OUTPUT: Did not explode

L'explosion dans votre code se produit pendant le rendu de .gist pendant say qui parcourt les 100 premiers éléments de votre Array et appelle .gist sur eux. Lorsqu'il le fait sur le Failure l'élément, il le fait exploser.

Vous confondez l'enfoncement de l'objet liste lui-même et l'enfoncement des valeurs individuelles qu'il contient. Vous avez correctement mentionné List.sink est un no-op, mais Seq.sink se consomme elle-même¹, et pourtant elle n'explosera pas non plus, parce que juste la Seq est coulé, pas ses éléments individuels : (+"a", 42).Seq.sink

Si vous voulez forcer le potentiel Failure des explosions, vous pourriez :

1 : use fatal . Cela entraînera la fatalisation des échecs du compilateur, provoquant leur détonation à de nombreux endroits où Failures circulent. Il s'agit d'un pragme lexical et il est aussi automatiquement activé dans la fonction try {} blocs.

use fatal;
sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink;

# OUTPUT:
# boo!
#  in block <unit> at

2 : Hyper sur .self l'appel de la méthode. Il est fourni par Mu (donc hérité par tous les objets) et renvoie simplement self Il n'y a donc pas de possibilité (autre que de faire un décontamination ). Toutefois, étant donné que la plupart des méthodes appelées sur l'armée Failure les faire exploser, en appelant .self sur eux va les faire exploser.

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink».self;

# OUTPUT:
# boo!
#  in block <unit> at

Comment puis-je déboguer dans ces fonctions en utilisant le débogueur Perl 6 ou un module ?

Je n'utilise pas de débogueur moi-même, mais perl6-debug-m devrait être préinstallé avec votre installation de Rakudo. Il vous faut installer Debugger::UI::CommandLine module. Et vous l'utilisez simplement à la place de perl6 pour exécuter votre programme et il devrait vous donner des instructions sur la ligne de commande pour savoir ce qu'il fait. Il y a aussi un article de blog à ce sujet y une vidéo (nécessite Flash pour être lu).

Il y a aussi une version de qualité alpha, récemment publiée. App::MoarVM::Debug qui vous permet de déboguer des programmes même à distance. Sa beauté réside dans le fait qu'il vous permet de vider les entrailles de l'objet et d'y naviguer pendant que le programme est en cours d'exécution, donc si vous pouvez supporter son interface, il peut être utile.

Personnellement, je débogue en utilisant simplement dd la routine de déverser des trucs à des endroits stratégiques et de voir s'ils contiennent les choses que j'attends d'eux.

Comment puis-je savoir si List.sink est effectivement appelé ou, en général, si sink est appelé lorsqu'un objet se trouve dans un contexte de sink ?

Vous pouvez mélanger un rôle en utilisant does o but qui fournit un sink une méthode qui fait quelque chose que vous pouvez regarder. Comme imprimer quelque chose :

sub foo {
    return [<a b c>] does role { 
        method sink { say "sink called" }
    }
}
foo
# OUTPUT: sink called

Une méthode plus avancée serait de vider les données post-optimisation. Arbre QAST et voir s'il contient les appels que vous attendez. CoreHackers::Q rend l'arbre QAST vidé plus facile à visualiser.

P.S. : au sujet de l'enfoncement implicite, il convient de noter que R#1571 qui énumère plusieurs bogues et propose que les systèmes internes de gestion de l'enfoncement soient entièrement repensés.


¹ - plus précisément, Seq.sink appelle .sink-all sur son Iterator qui, par défaut, consomme simplement les valeurs, mais les itérateurs personnalisés peuvent surcharger cette méthode pour qu'elle soit également sans effet.

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