2017-04-09 2 views
7

Peut-être que ma vraie question est "Est-ce une fonctionnalité appropriée pour Learning Perl 6"? Basé sur Should this Perl 6 CATCH block be able to change variables in the lexical scope?, il semble que l'exemple le plus simple pourrait être au-delà d'un simple exemple.Quand est-ce que je voudrais reprendre une exception Perl 6?

Dans cette question, je travaillais avec quelque chose qui semble être idiot ou mieux d'une autre manière pour ce problème particulier parce que je jouais avec la fonctionnalité plutôt que de résoudre un problème. Il y a l'utilisation documentée des avertissements comme des exceptions spéciales ("exceptions de contrôle") où vous recevez le message, vous pouvez l'attraper si vous le souhaitez, mais vous pouvez aussi l'ignorer et il reprendra tout seul (bien que je sois plutôt stupide à ce sujet dans Where should I catch a Perl 6 warning control exception?). Au-delà de cela, je pense à des choses où l'appelant peut gérer une défaillance en dehors de la portée de l'appelé. Par exemple, se reconnecter à une base de données, réparer les répertoires manquants et autres problèmes de ressources externes dont l'appelé n'est pas responsable. En lisant ce genre de choses dans d'autres langues, le conseil a surtout été de ne pas les utiliser car dans la programmation "en monde réel" les gens ont tendance à ne pas vraiment gérer le problème de toute façon.

La réponse à C# exception handler resume next semble dire que c'est une mauvaise pratique et un code moche. Je n'ai certainement pas trouvé un moyen de cacher un tas de code dans l'appelé.

J'ai piraté cet exemple, même si je ne suis pas convaincu que ce soit un bon moyen de le faire ou quelque chose à recommander aux débutants. Le programme recherche un fichier PID au démarrage. S'il en trouve un, il lance une exception. La gestion de cette exception vérifie que l'autre instance est toujours en cours d'exécution, ce qui peut générer un type d'exception différent. Et, il y a celui pour gérer les problèmes d'IO de fichier. L'astuce est que le X::MyProgram::FoundSemaphore peut reprendre si l'autre programme n'est pas en cours d'exécution (mais a laissé son fichier PID derrière).

+1

Pas important pour la question, mais notez que 'BEGIN' s'exécute au moment de la compilation. Les modules sont compilés au moment de l'installation, donc ce code placé dans un module ne fait probablement pas ce qui est prévu. 'INIT' semblerait un meilleur pari pour le démarrage de programme, et fonctionnera bien dans le cas de module. –

+0

Oui, INIT semble mieux. –

Répondre

6

exceptions ne sont pas certainement réactivables quelque chose que je me suis trouvé en Perl pour atteindre 6. Je ne pense pas que je les ai utilisés du tout encore dans le code « userspace ». Une exception resumable s'est avérée être la bonne façon d'implémenter la fonction emit, utilisée dans les blocs supply et react. La fonction take utilisée dans gather est également implémentée à l'aide d'une exception resumable, et - comme vous l'avez déjà constaté - warn les utilise. Je pense que le dernier de ces - warn - est le seul cas qui intéresserait l'utilisateur typique de Perl 6. Capturer des avertissements et les envoyer ailleurs - peut-être dans un fichier journal ou un serveur de journalisation - est une chose plutôt raisonnable. besoin de faire. En ce qui concerne Learning Perl 6, c'est probablement l'exemple le plus évident d'une exception pouvant être reprise.

Je pense qu'il est significatif que tous les cas d'utilisation qui tirent parti des exceptions pouvant être reprises dans Perl 6 se révèlent être des choses classifiées comme des "exceptions de contrôle". Les exceptions de contrôle sont essentiellement des exceptions normales au niveau de la mise en œuvre: elles impliquent un transfert de contrôle non local. Ils sont faits distincts au niveau de la langue, car il serait plutôt difficile à utiliser Perl 6 si votre emit, take, warn, next, last et ainsi de suite cessé de travailler en raison d'un bloc CATCH avec un default avaler les exceptions de contrôle!Cependant, c'est aussi un peu "faire ce que je dis, pas ce que je fais": tandis que Perl 6 est heureux d'utiliser le système d'exception pour implémenter le contrôle de flux non local, il le clôt un peu dans un coin poussiéreux de la langue plutôt que de le présenter comme un exemple de quelque chose à faire. Et pour cause: généralement, le code qui utilise des exceptions pour contrôler le flux est difficile à suivre, et cela double pour les exceptions pouvant être reprises. L'autre grand risque est que de telles exceptions puissent être avalées par un code qui utilise un try nu ou un CATCH avec un default - ce qui en fait une chose plutôt fragile à faire dans une base de code plus grande. J'imagine que les meilleures utilisations des exceptions resumables se révéleront être une stratégie de mise en œuvre pour des choses auxquelles les utilisateurs ne penseront pas du tout en termes d'exceptions - comme c'est le cas avec take et emit (et la plupart du temps, warn). Et, comme pour les exemples existants d'exceptions pouvant être reprises, la chose à reprendre sera un type d'exception qui a été spécifiquement conçu pour être jeté dans des situations de reprise et utilisé seulement dans les cas où c'est une chose sensée à faire. Jusqu'à ce que Perl 6 fournisse un moyen de définir des exceptions de contrôle personnalisées, je serais plutôt réticent à le faire; le problème de déglutition try/default le rend tout simplement trop fragile.

+0

Un cas d'utilisation pour une exception pouvant être reprise avec $ * ARGFILES rencontrant un mauvais fichier: https://stackoverflow.com/questions/48865412/how-should-i-handle-perl-6-argfiles-that-cant-be-read -by-lines –