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.