2010-06-25 14 views
5

A continuación está mi código (no se preocupe, hay un USUW en la parte superior del módulo)¿Alguien puede explicarme esta excepción de solo lectura?

Estoy probando si una matriz de referencia es de solo lectura, y si ese es el caso, entonces la estoy copiando en otra matriz ref. Las pruebas muestran que la matriz no es de solo lectura, sin embargo, cuando se ejecuta, falla con ese error. (Para aquellos que no estén familiarizados conmigo o Smart::Comments --those ### son Smart::Comments.)

### readonly($arg_ref) : readonly($arg_ref) 
### readonly(@$arg_ref) : readonly(@$arg_ref) 
my @ro = map { readonly($_) } @$arg_ref; 
### @ro 
if (readonly $arg_ref) { 
    $arg_ref = [ @$arg_ref ]; 
} 
return map { my $val = shift @$arg_ref; 
      $_ => $val 
      } @_ 
      ; 

Ésta es la salida me sale:

### readonly($arg_ref) : 0 
### readonly(@$arg_ref) : 0 

### @ro: [ 
###  0, 
###  0, 
###  0, 
###  0, 
###  0 
###  ] 

Pero aquí está el error:

Modification of a read-only value attempted at ....pm line 247. 

(247 es:

return map { my $val = shift @$arg_ref; 

)

¿Alguien tiene alguna familiaridad con este problema? Estamos ejecutando Perl 5.8.7. ¿Alguna idea sobre cómo abordarlo?

+0

¿De dónde viene el símbolo 'readonly'? No creo que el módulo Readonly proporcione uno. – Ether

+0

@Ether es ['Scalar :: Util :: readonly'] (http://search.cpan.org/perldoc?Scalar::Util#readonly) – Axeman

+0

¿Cómo está' $ arg_ref' obteniendo su valor? –

Respuesta

0

No se ve como el resultado de Scalar::Util::readonly puede ser utilizado confiar cómo desea utilizarlo. Testigo:

perl -MScalar::Util=readonly -MReadonly -wle' 
    Readonly my $arg_ref => [ qw(a b c)]; 
    print readonly $arg_ref; 
    $arg_ref = 1;' 

impresiones:

0 
Modification of a read-only value attempted at -e line 1. 

(Sometido a pruebas en perl5.8.8 con 1,03 Sólo lectura, Scalar :: Util 1,23)

+1

Es una lástima, y ​​en un módulo básico, también ... – Axeman

+0

Acabo de ejecutar la prueba anterior en perl5.12.1 y obtuve el mismo resultado. :( – Ether

+0

Eso es porque Readonly y readonly son cosas diferentes. :) Consulte mi respuesta para saber por qué. –

2

Si la referencia de DBI::fetchrow_arrayref está volviendo de sólo lectura, el intento de sobrescribir no ayudará a: la referenciaes de sólo lectura, no el thingie (es decir, la matriz con valores de columna).

Haga su propia copia en el origen si necesita actualizaciones destructivas, p.,

my $arg_ref = [ $sth->fetchrow_array ]; 
+0

@Axeman Pero si '$ arg_ref' puede ser de solo lectura, las operaciones destructivas como' shift' no son adecuadas, lo que ha observado. –

+0

de hecho y parte de la programación es la solución de problemas. Una cola es * transportable * una "secuencia de lista" no lo es a menos que desee improvisar una combinación de lista y lugar actual en la lista. Pero eso nunca haría más que una buena cola pasada de moda que obtienes de forma gratuita con una matriz de Perl. Ahora, puedo * siempre * copiarlo, pero un "pito de rendimiento y eficiencia" como yo nos da colmenas pensando en no hacer solo lo que se necesita. – Axeman

+0

@Axeman ¡Respuesta actualizada-destructivamente, incluso! –

1

de solo lectura y de sólo lectura son diferentes. (Nótese la capital R y r minúscula ;-).)

Consulte la documentación Scalar::Util por qué esto es cierto:

readonly SCALAR

Returns true if SCALAR is readonly.

sub foo { readonly($_[0]) } 
$readonly = foo($bar);    # false 
$readonly = foo(0);     # true 

Esto es más acerca de los alias (como los que pasó a través de foreach o en . @_, y no el módulo Sólo lectura

+0

Entonces, ¿hay alguna manera de verificar si una variable se declaró Readonly con una R mayúscula? – Ether

+2

Tanto Readonly :: XS como la implementación XS de solo lectura se basan en la misma bandera (SvREADONLY), por lo que deberían ser las mismas (si está utilizando las versiones XS, lo cual debería hacer). Huelo un error aquí. –

+1

@Ether, IIUC, 'ref (tied (A_VARIABLE)) = ~/^ Readonly :: /' debería hacer el truco, y querrá volver a consultar 'Scalar :: Util :: readonly' si ese control Es falso. – pilcrow

1

creo que tengo todo resuelto Robert P estaba en lo cierto, pero sólo recibió la mitad de la respuesta:. Readonly y readonly hacer cosas diferentes aunque deberían hacer lo mismo, el hecho que no es un error. Trataré de explicar lo que está pasando.

Readonly tiene dos implementaciones para escalares: uno (Readonly::XS) que se basa en la bandera SvREADONLY y uno (Sólo lectura :: escalares) basado en los lazos que emula la bandera SvREADONLY.

readonly también tiene dos implementaciones, una en Perl (que realiza la autoasignación y comprueba si arroja una excepción o no), y otra en XS (nuevamente basada en el indicador SvREADONLY).

Hay 4 combinaciones posibles, y desafortunadamente la que es más común (pure perl Readonly y XS readonly) es la única que no funciona como se anuncia.

Aquí está el quid: sub Readonly::Readonly en realidad no usa Readonly::XS en absoluto, solo sub Readonly::Scalar hace. Esto es probablemente un error. readonlycorrectamente informa que la variable no es una variable de solo lectura: su legibilidad se simula mediante un empate.

Es Readonly que tiene la culpa aquí OMI, debe hacer lo correcto cuando puede y documentar cuando no puede. En este momento no está haciendo ninguno de esos.

+0

Desde mi punto de vista, no hay ningún problema con 'Readonly', ni siquiera lo tenemos instalado en nuestro entorno. Lo único que me preocupa es la incapacidad de 'Scalar :: Util :: readonly' para decirme que una matriz hace referencia a una matriz de referencia es solo de lectura hasta que intento desplazarme en ella. – Axeman

+0

En realidad parece que no es la matriz * referencia * no es solo de lectura, sino la matriz a la que se refiere. Una diferencia sutil pero importante. –

+0

Este comportamiento definitivamente contradice la documentación: dice que cuando se tiene Readonly :: XS instalado, se usa en todos los casos para escalares (pero no para matrices y hashes). Gorrón. (Entonces, ¿quién va a presentar un error, o mejor aún enviar un parche?) :) – Ether

Cuestiones relacionadas