2010-05-04 13 views
8

Ce morceau de code se comporte différemment en Perl 5.8 qu'il ne sous Perl 5.12:Quelle est la différence dans l'évaluation retardée du code dans les sous-programmes pour Perl 5.8 par rapport à 5.10 et 5.12?

my $badcode = sub { 1/0 }; 
print "Made it past the bad code.\n"; 

Quand je lance sous 5.8, je reçois une erreur même si j'exercerai jamais la division:

[[email protected] tmp]$ /usr/bin/perl -v 

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi 

[[email protected] tmp]$ /usr/bin/perl badcode.pl 
Illegal division by zero at badcode.pl line 1. 

[[email protected] tmp]$ /usr/local/bin/perl -v 

This is perl 5, version 12, subversion 0 (v5.12.0) built for i686-linux 

[[email protected] tmp]$ /usr/local/bin/perl badcode.pl 
Made it past the bad code.

sous Perl 5.10.1, il se comporte comme il le fait sous 5,12:

[email protected]:/var/tmp$ perl -v 

This is perl, v5.10.1 (*) built for i486-linux-gnu-thread-multi 

[email protected]:/var/tmp$ perl badcode.pl 
Made it past the bad code.

-je obtenir les mêmes résultats avec un sous-programme nommé, par exemple

sub badcode { 1/0 } 

Je ne vois rien à ce sujet dans le pod perl5100delta. Est-ce un changement non documenté? Un effet secondaire involontaire d'un autre changement? (Pour mémoire, je pense que 5.10 et 5.12 sont en train de faire la bonne chose.)

+0

Je ne connais pas la réponse, mais il me semble que Perl 5.10+ a également différé les optimisations lexicales, telles que le précomputing '1/0'. Je ne sais pas si l'une ou l'autre façon est considérée comme "la bonne chose". – spoulson

Répondre

17

Je crois que cela a été prévu, et je ne vois cette mention in perl5100delta.pod:

Exceptions dans le repliement constant

Le la routine de pliage constante est maintenant enveloppée dans un gestionnaire d'exceptions, et si le pliage génère une exception (telle que en essayant d'évaluer 0/0), perl conserve maintenant l'optree actuel, plutôt qu'abandonner le programme entier. Sans ce changement, les programmes seraient ne compilera pas si elles avaient des expressions qui se sont produits pour générer des exceptions, même si ces expressions étaient dans le code qui ne pourrait jamais être atteint à exécution. (Nicholas Clark, Dave Mitchell )

Il vient de faire à l'exception ne résultant pas divisé par zéro dans une compilation abort étapes.

+0

Merci, Evan. Maintenant, j'ai besoin de comprendre comment contourner cela dans les tests sous perl 5.8, car j'utilisais ce code pour tester un cas de bord. * grumble * – Brock

+0

@Brock: Je ne sais pas si cela fonctionnerait comme je n'ai jamais eu à le faire, mais avez-vous envisagé de piéger l'erreur en utilisant un wrapper 'eval'? – Zaid

+0

@Zaid non parce que le repliement constant se produit avant l'eval pendant la génération de l'op-tree. eval ne fait que mettre en cache un op-tree. ex, 'eval {1/1}', n'est effectivement pas différent à l'exécution de 'eval {1}'. –