2010-07-19 8 views
5

strftime(), según cpan.org:Perl: No se puede aprobar una "sobre la marcha" matriz a un sub

print strftime($template, @lt); 

No puedo imaginar la derecha receta código Perl para éste. Mantiene informar un error cuando llamo 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 uso() para pasar la matriz requerida por strftime(), me sale: Tipo de arg 2 hasta la fecha :: :: formato strftime debe ser una matriz (no lista) en ./blah.pl línea 87, cerca de "))"

Si uso [] para pasar la matriz requerida, obtengo: Tipo de arg 2 a Fecha :: Formato: : strftime debe ser una matriz (no lista anónima ([])) en ./blah.pl línea 87, cerca de "])"

¿Cómo puedo pasar una matriz sobre la marcha a un submarino en Perl? Esto se puede hacer fácilmente con PHP, Python, JS, etc. Pero no puedo entenderlo con Perl.

EDIT: reduce el código para estas pocas líneas, y todavía tiene el mismo 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)); 

Respuesta

7

Cuando se necesita una matriz y tiene una lista ad hoc, necesita crear una matriz. No tiene por qué ser una variable independiente, puede hacer precisamente:

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

no tengo idea de qué fecha :: Formato se sometería a esta fealdad y no sólo esperar varios parámetros escalares; parece absurdo (y contrario a cómo otros módulos implementan strftime). Graham Barr generalmente diseña mejores interfaces que esta. Tal vez data de cuando los prototipos aún parecían una idea genial para propósitos generales.

+0

¡Esto también funciona! Mejor, ya que evita la necesidad de una variable de marcador de posición –

0

miré de nuevo y ver el verdadero problema en este código:

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

Específicamente @{$details->{'date_added'}} es una desreferencia. Pero estás de asignarlo a una variable escalar y no es necesario eliminar la referencia en la línea debajo de él:

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

He creado una matriz regular para su referencia @d y acaba de acceder como un conjunto regular ($d[ ... ] en lugar de @$d[ ... ])

2

Normalmente, es fácil pasar arrays "sobre la marcha" a las subrutinas Perl. Pero Date::Format::strftime es un caso especial con un prototipo especial ($\@;$) que no permite argumentos "lista" o "argumentos": lista de asignación

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 solución es que se debe llamar strftime con una variable de matriz.

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

¡Trabajos! Gracias. Me gustaría poder darle sentido a "($ \ @; $)" –

+2

@ R.Hill: ver [perldoc perlsub] (http://perldoc.perl.org/perlsub.html) para obtener detalles sobre las especificaciones del prototipo de la función. – Ether

+0

Por cierto, este es el uso más horrible de los prototipos de Perl que he visto. :) – fennec

3

utilizar una lista como una matriz en el anonimato para, por ejemplo, la interpolación de cadenas, se podría escribir

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

para obtener

1 2 3

La misma técnica ofrece una solución para el prototipo moderno 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]}); 

Salida:

1900-24709920-00T12:00:00
Cuestiones relacionadas