2010-11-04 3 views
1

J'essaie d'utiliser Moose. C'est génial, quand ça marche. Cependant, j'ai trouvé quelque chose qui ressemble à un bug (mais je vais demander ici avant de le commettre).Pourquoi ce sous-programme de coercition de Moose ne fonctionne-t-il pas sur Perl 5.8.8?

Quand je lance ce code

package Experiment; 

use Moose; 
use Moose::Util::TypeConstraints; 

subtype 'K' 
    => as 'Str'; 

coerce 'K' 
    => from 'Str' 
    => via { 
     s/^([^_]*).*$/$1/; 
    }; 

has 'k' => (
    is => 'ro', 
    isa => 'K', 
    coerce => 1 
); 

1; 
package main; 

my $exp = new Experiment(k=>"abcd_efgh"); 
print $exp->k."\n"; 

Sur un ordinateur avec perl 5,010, il montre correctement abcd. Quand je l'exécute sur un autre ordinateur avec 5.8.8 (où le script, malheureusement, doit fonctionner aussi), je vois incorrect abcd_efgh; et le sous-programme de coercition ne semble jamais fonctionner réellement (si j'ajoute une impression ou meurs là, par exemple, rien ne se passe sur la machine 5.8.8).

(Il est vraiment simplifié, mais il est un cas de la vie réelle réelle - je dois forcer K à partir de chaînes, qui ont toujours des déchets après underscore)

Pensez-vous qu'il est un bug Moose?

+0

Les versions Moose sont-elles à jour? – daxim

+0

Oui, c'est 1,19, selon le CPAN. –

Répondre

6

Si vous utilisez vraiment perl 5.8.0, ce n'est pas un bug, car Moose requires a minimum version of perl 5.8.3. Pardon.

Etes-vous vraiment sûr de ne pas pouvoir mettre à niveau? 5.8.0 est vraiment très ancien, et le passage à 5.8.8 (qui est lui-même assez ancien, mais qui fonctionne encore dans de nombreux environnements d'entreprise) vous permettra d'acheter beaucoup de corrections de bogues.

Mais (merci de le remarquer), votre contrainte ne s'exécutera jamais, car la contrainte de type existante 'K' passera. Vous devez ajouter une clause where à la définition du sous-type, afin de déclencher la contrainte:

subtype 'K' 
    => as 'Str' 
    => where { $_ !~ /_/ }; 

coerce 'K' 
    => from 'Str' 
    => via { 
     m/^([^_]*).*$/; $1; 
     # this is an alternate method: 
     # (split('_', $_, 2))[0]; 
    }; 

(Notez que l'opérateur de substitution retourne le nombre de substitutions effectuées, j'ai proposé deux réécritures alternatives ci-dessus.)

Enfin, le code tel que vous l'avez écrit dans votre question imprime "abcd_efgh" sur un système entièrement opérationnel, alors êtes-vous sûr que vous utilisez le même code sur les deux cases?

+0

Oh. J'ai trop simplifié dans le code que j'ai collé sur SO ... oui, mon code renvoie le numéro, j'avais une ligne de code de plus (lc) dans mon cas. Mais principalement, la clause Where corrige tout. Merci de l'avoir signalé! (le perl est, en fait, pas 5.8.0, mais 5.8.8 Désolé pour le mélange) –

+1

@Karel: que se passe-t-il lorsque vous exécutez le code * exact * que vous avez inclus dans votre question sur une boîte perl5.10? La coercition ne devrait pas fonctionner, comme je l'ai décrit ci-dessus. – Ether

+0

Ether: Désolé, c'était de ma faute en simplifiant le code à coller ici. MAIS. Sur la boîte de 5.10, il contraint même sans la clause where. –

Questions connexes