2009-11-12 10 views
8

que tienen un archivo Perl así:¿Por qué me llaman "advertencias demasiado pronto para verificar prototipos" en mi código Perl?

use strict; 
f1(); 

sub f3() 
{ f2(); } 

sub f1() 
{} 
sub f2() 
{} 

En resumen, f1 se llama antes de que se define. Entonces, Perl lanza una advertencia: "f1 llamó demasiado temprano para verificar el prototipo". Pero igual es el caso con f2, la única diferencia es que se llama desde dentro de otra subrutina. No arroja una advertencia para f2. ¿Por qué?

¿Cuál es la mejor manera de resolver este problema?

  1. declaran la subrutina antes de que se llama
  2. ir al sub así: &f1();
+3

Utilice el formato al publicar ejemplos de código: sangría líneas por 4 espacios hará que aparezcan como código en la pregunta, con resaltado y todo. –

+0

Debería agregar el modificador -w si realmente quiere que esto falle –

Respuesta

14

Usted puede evitar completamente este problema no utilizando prototipos en el primer lugar:

use strict; 

f1(); 

sub f3 { f2() } 

sub f1 {} 
sub f2 {} 

Don't use prototypes a menos que sepa por qué los está utilizando:

Todo esto es muy poderoso, por supuesto, y debe usarse solo con moderación para hacer del mundo un lugar mejor.

+1

No me gusta el bit "no usar prototipos". Son bastante agradables a veces, para algunas cosas. –

+0

No utilizar prototipos es una de las razones por las que las personas se quejan de la legibilidad y la facilidad de mantenimiento en Perl. – jheddings

+5

@jheddings: Te estás perdiendo el punto: los prototipos de Perl son, 99%, * una característica no útil *. Hacen que el código * empeore *. No me creas? Lee http://groups.google.com/group/comp.lang.perl.modules/msg/84484de5eb01085b?dmode=source&output=gplain&pli=1. El único prototipo útil en perl es '(&; @)'. – hobbs

2

La falta de una advertencia en la llamada a partir de f2()f3() parece ser un error.

use strict; 
use warnings; 

f1(); 

sub f1 { 
    my @a = qw(a b c); 
    f2(@a); 
} 

sub f2(\@) { print $_[0] } 

Esto imprime "a". Si declara f2() o cambia el orden de las definiciones de la subrutina, imprime "ARRAY (0x182c054)".

En cuanto a la resolución de la situación, depende. Mis preferencias (en orden) serían:

  1. Elimine los prototipos de las definiciones de la subrutina. Los prototipos de Perl no hacen lo que la mayoría de la gente espera de ellos. En realidad, solo son útiles para declarar sub que actúan como construcciones internas. A menos que intente extender la sintaxis de Perl, no los use.
  2. Predeclare las subrutinas antes de usarlas. Esto le permite a Perl saber sobre el prototipo antes de encontrar cualquier llamada.
  3. Reordenar el código para que las definiciones de subrutina aparezcan antes de cualquier llamada.
  4. Llamar a las subrutinas utilizando la notación &foo() para eludir la comprobación de prototipos.
2

Si va a llamarlo con el paréntesis, ¿por qué está utilizando prototipos?

sub f1(){ ... } 

f1(); 

La única vez que me gustaría utilizar el prototipo vacía es una subrutina que quiero trabajar como una constante.

sub PI(){ 3.14159 } 

print 'I like ', PI, ", don't you?\n"; 

De hecho, me recomendamos el uso de Perl 5 prototipos, a menos que usted quiere que su subrutina se comporte de manera diferente de lo que sería de otra manera.

sub rad2deg($){ ... } 

say '6.2831 radians is equal to ', rad2deg 6.2831, " degrees, of course.\n"; 

En este ejemplo, tendría que usar paréntesis, si no tenía un prototipo. De lo contrario, habría recibido un argumento adicional, y la última cadena nunca se imprimiría.

+0

Tiene una "\ n" espuria al final de la instrucción say allí –

+0

Quise cambiarla a 'print' para no tener que' usar la característica qw'say '; 'o' use 5.10 .1; ' –

4

Simplemente elimine el() de las definiciones de subrutina. Cuando defines con(), Perl piensa que estos son prototipos y tienes que definir tu prototipo antes de usarlo.

Prueba esto ......

use strict; 
f1(); 

sub f3 
{ f2(); } 

sub f1 
{} 
sub f2 
{} 
0

Cuando se define una función en Perl no se debe utilizar paréntesis. Cuando lo haces, obtienes este error. Esto está mal:

sub DoSomthing(){ 
    #do what ever... 
} 

Este es el camino a seguir:

sub DoSomthing{ 
    #do what ever... 
} 

sin paréntesis.

Para obtener información más detallada, consulte la página Perl Maven de Gabor Szabo sobre Subrutinas y funciones en Perl. https://perlmaven.com/subroutines-and-functions-in-perl

Cuestiones relacionadas