2010-07-19 5 views
5

strftime(), selon cpan.org:Perl: ne peut pas passer un « à la volée » tableau à un sous

print strftime($template, @lt); 

Je ne peux pas comprendre la bonne recette de code Perl pour celui-là. Il garde de rapporter une erreur où j'appelle strftime():

... 
use Date::Format; 
... 
sub parse_date { 
if ($_[0]) { 
    $_[0] =~ /(\d{4})/; 
    my $y = $1; 
    $_[0] =~ s/\d{4}//; 
    $_[0] =~ /(\d\d)\D(\d\d)/; 
    return [$2,$1,$y]; 
    } 
return [7,7,2010]; 
} 

foreach my $groupnode ($groupnodes->get_nodelist) { 
    my $groupname = $xp->find('name/text()', $groupnode); 
    my $entrynodes = $xp->find('entry', $groupnode); 
    for my $entrynode ($entrynodes->get_nodelist) { 
     ... 
     my $date_added = parse_date($xp->find('date_added/text()', $entrynode)); 
     ... 
     $groups{$groupname}{$entryname} = {...,'date_added'=>$date_added,...}; 
     ... 
     } 
    } 
... 

my $imday = $maxmonth <= 12 ? 0 : 1; 
... 

while (my ($groupname, $entries) = each %groups) { 
    ... 
    while (my ($entryname, $details) = each %$entries) { 
     ... 
     my $d = @{$details->{'date_added'}}; 
     $writer->dataElement("creation", strftime($date_template, (0,0,12,@$d[0^$imday],@$d[1^$imday]-1,@$d[2],0,0,0))); 
     } 
    ... 
    } 
... 

Si j'utilise() pour passer le tableau requis par strftime(), je reçois: Type de arg 2 à Date :: Format :: strftime doit être array (not list) à ./blah.pl ligne 87, près de "))"

Si j'utilise [] pour passer le tableau requis, j'obtiens: Type d'argument 2 à Date :: Format: : strftime doit être array (pas la liste anonyme ([])) à ./blah.pl ligne 87, près de "])"

Comment puis-je transmettre un tableau à la volée à un sub en Perl? Cela peut facilement être fait avec PHP, Python, JS, etc. Mais je ne peux pas le comprendre avec Perl.

EDIT: Je réduit le code à ces quelques lignes, et j'ai toujours eu le même problème:

#!/usr/bin/perl 

use warnings; 
use strict; 
use Date::Format; 

my @d = [7,13,2010]; 
my $imday = 1; 
print strftime(q"%Y-%m-%dT12:00:00", (0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0)); 

Répondre

7

Lorsqu'un tableau est requis et que vous avez une liste ad hoc, vous devez créer un tableau. Il n'a pas besoin d'être une variable séparée, vous pouvez le faire:

strftime(
    $date_template, 
    @{ [0,0,12,$d[0^$imday],$d[1^$imday],$d[2],0,0,0] } 
); 

Je n'ai aucune idée pourquoi Date :: Format voulez-vous soumettre à cette hideur et ne pas attendre que plusieurs paramètres scalaires; semble insensé (et contrairement à la façon dont les autres modules implémentent strftime). Graham Barr conçoit généralement de meilleures interfaces que celle-ci. Peut-être que ça date de quand les prototypes semblaient encore être une bonne idée pour des raisons générales.

+0

Cela fonctionne aussi! Mieux, puisqu'il évite le besoin d'une variable d'espace réservé –

0

Je regardais à nouveau et je vois le vrai problème dans ce code:

my $d = @{$details->{'date_added'}}; 
    $writer->dataElement("creation", strftime($date_template, (0,0,12,@$d[0^$imday],@$d[1^$imday]-1,@$d[2],0,0,0))); 

Spécifiquement @{$details->{'date_added'}} est une déréférence. Mais vous l'assigner à une variable scalaire et vous n'avez pas besoin de déréférencer dans la ligne en dessous:

my @d = @{$details->{'date_added'}}; 
    $writer->dataElement("creation", strftime($date_template, (0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0))); 

J'ai créé un réseau régulier pour votre référence @d et juste accédaient un tableau à ($d[ ... ] au lieu de @$d[ ... ])

2

Normalement, il est facile de passer des tableaux "à la volée" aux sous-programmes Perl. Mais Date::Format::strftime est un cas particulier avec un prototype ($\@;$) spécial qui ne permet pas d'arguments ou des arguments « d'affectation de la liste » « liste »:

strftime($format, (0,0,12,13,7-1,2010-1900));  # not ok 
strftime($format, @a=(0,0,12,13,7-1,2010-1900)); # not ok 

La solution est que vous devez appeler strftime avec une variable de tableau.

my @time = (0,0,12,13,7-1,2010-1900); # note: @array = (...), not [ ... ] 
strftime($format, @time); 
+0

Fonctionne! Merci. Je voudrais pouvoir donner un sens à "($ \ @; $)" –

+2

@ R.Hill: voir [perldoc perlsub] (http://perldoc.perl.org/perlsub.html) pour plus de détails sur les spécifications des prototypes de fonctions. – Ether

+0

Incidemment, c'est l'utilisation la plus hideuse des prototypes Perl que j'ai jamais vus. :) – fennec

3

Pour utiliser une liste comme un tableau anonyme pour, par exemple, l'interpolation de chaîne, vous pouvez écrire

print "@{[1, 2, 3]}\n"; 

pour obtenir

1 2 3

La même technique fournit une solution de contournement pour prototype génial de Date::Format::strftime :

print strftime(q"%Y-%m-%dT12:00:00", 
       @{[0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0]}); 

Sortie:

1900-24709920-00T12:00:00
Questions connexes