2010-07-19 10 views
5

strftime(), come da cpan.org:Perl: Non può superare un "on-the-fly" array ad un sub

print strftime($template, @lt); 

io proprio non riesco a capire il diritto ricetta codice Perl per questo. Mantiene segnalato un errore di cui io chiamo 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))); 
     } 
    ... 
    } 
... 

Se uso() per passare la matrice richiesto da strftime(), ottengo: Tipo di arg 2 to Date :: Format :: strftime deve essere array (non lista) in ./blah.pl riga 87, vicino a "))"

Se uso [] per passare l'array richiesto, ottengo: Tipo di argomento da 2 a Data: Formato: : strftime deve essere array (non elenco anonimo ([])) in ./blah.pl riga 87, vicino a "])"

Come posso passare un array al volo a un sotto in Perl? Questo può essere fatto facilmente con PHP, Python, JS, ecc. Ma non riesco a capirlo con Perl.

EDIT: ho ridotto il codice per queste poche righe, e ho ancora avuto lo stesso identico problema:

#!/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)); 

risposta

7

casi in cui è necessaria una matrice e si dispone di una lista ad hoc, è necessario creare effettivamente una matrice. Non ha bisogno di essere una variabile indipendente, si può fare proprio:

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

non ho alcun indizio perché Data :: Format si sottoporrebbe a questo orrore e non solo si aspettano più parametri scalari; sembra insensato (e contrariamente a come gli altri moduli implementano lo strftime). Graham Barr di solito progetta interfacce migliori di questa. Forse risale a quando i prototipi sembravano ancora un'idea interessante per scopi generali.

+0

Anche questo funziona! Meglio, dal momento che evita la necessità di una variabile segnaposto –

0

ho guardato di nuovo e vedo il vero problema in questo codice:

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))); 

In particolare @{$details->{'date_added'}} è un dereferenziazione. Ma si sta assegnandolo ad una variabile scalare e non è necessario per dereference nella riga sotto di essa:

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))); 

Ho creato una serie regolare per il vostro riferimento @d e appena entrato come una serie regolare ($d[ ... ] anziché @$d[ ... ])

2

Normalmente, è facile passare gli array "al volo" alle subroutine Perl. Ma Date::Format::strftime è un caso particolare con un prototipo speciale ($\@;$) che non consente "Lista" argomenti o "assegnazione lista" argomenti:

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 soluzione è che è necessario chiamare strftime con una variabile array.

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

Opere! Grazie. Vorrei poter dare un senso a "($ \ @; $)" –

+2

@ R.Hill: vedere [perldoc perlsub] (http://perldoc.perl.org/perlsub.html) per i dettagli delle specifiche del prototipo di funzione. – Ether

+0

Per inciso, questo è l'unico uso più orribile dei prototipi Perl che abbia mai visto. :) – fennec

3

Per utilizzare una lista come un array anonimo per, diciamo, interpolazione stringa, si potrebbe scrivere

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

per ottenere

1 2 3

La stessa tecnica fornisce una soluzione per il prototipo funky Date::Format::strftime s' :

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

Uscita:

1900-24709920-00T12:00:00
Problemi correlati