2012-04-26 18 views
42

De acuerdo con doc, la instrucción while ejecuta el bloque siempre que la expresión sea true. Me pregunto por qué se convierte en un bucle infinito con una expresión vacía:Perl: mientras que no condicional

while() { # infinite loop 
... 
} 

¿Es sólo inexactitud en el doc?

+5

Prefiero 'while (1)' para enfatizar la intención. – JRFerguson

Respuesta

34
$ perl -MO=Deparse -e 'while() { }' 
while (1) { 
    (); 
} 
-e syntax OK 

Parece que while() {} y while (1) {} son equivalentes. También tenga en cuenta que los paréntesis vacíos * se insertan en el bloque vacío.

Otro ejemplo de comportamiento compilador predefinido:

$ perl -MO=Deparse -e 'while (<>) { }' 
while (defined($_ = <ARGV>)) { 
    (); 
} 
-e syntax OK 

Yo diría que esto es sólo la documentación que no informaron un caso especial.

* — Para ser precisos, se inserta el código de operación stub. No hace nada, pero sirve un objetivo goto para el código de operación enterloop. No hay una razón real para notar esto. Deparse denota este stub op utilizando parens vacíos, ya que los parens no generan código.

+12

Curiosamente, 'for (;;)' deparses como 'while (1)' también. –

+3

@briandfoy Sí, noté que después de publicar esto ... otro caso especial.Aún más curiosamente 'for()' es un error de sintaxis, pero 'for (())' compila, pero no se compila en el caso 'while (1)', sino 'foreach $ _ (())'. – TLP

+0

@TLP No, ese último tiene sentido. 'for()' tiene dos sintaxis que conozco: C-style y foreach over list. Entonces no sabe cuál quieres. 'for (())' es un foreach sobre una matriz vacía: 'perl -e 'for (()) {print" foo ";}'' – Izkata

11

Este es un caso especial. Una expresión condición vacía por defecto simplemente true, que significa "bucle para siempre, o hasta que un break. En C (y Perl) el idioma

for(;;) { 
    // Neverending fun 
} 

tiene el mismo efecto por la misma razón.

Hay doesn 't parece haber ninguna mención de esto en los documentos oficiales de perl, y sin embargo no es una regla especial en el analizador para ello. Tal vez sea porque nadie lo usa :)

el idioma for(;;) es menos raro sin embargo.

+4

Si lo es, sin duda necesita una mención en el documento. – codaddict

+0

¿Está documentado esto en alguna parte? –

+1

Claro. Hay algunas cosas específicas definidas como false (0, "", undef). Todo lo demás es por defecto cierto. – delicateLatticeworkFever

14

Este es un caso especial del concepto de Vacuous Truth. Si no hay una condición, la declaración mientras la condición es verdadera es en sí misma vacuamente cierta.

Si estoy leyendo esto correctamente, la pieza correspondiente de código parece ser around line 5853 of op.c en 5.14.1:

5853  if (expr) { 
5854   scalar(listop); 
5855   o = new_logop(OP_AND, 0, &expr, &listop); 
5856   if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) { 
5857    op_free(expr);    /* oops, it's a while (0) */ 
5858    op_free((OP*)loop); 
5859    return NULL;    /* listop already freed by new_logop */ 
5860   } 
5861   if (listop) 
5862    ((LISTOP*)listop)->op_last->op_next = 
5863     (o == listop ? redo : LINKLIST(o)); 
5864  } 
5865  else 
5866   o = listop; 

Estoy asumiendo sin expr en la condición, se llega a o = listop. listop se definió anteriormente como listop = op_append_list(OP_LINESEQ, block, cont);.

+1

No creo que sea eso; que o = listop puede ser el caso 'while (())' sin bucle. 'while()' se implementa realmente en el analizador (perly.y); vea la regla texpr, que no es nada (en cuyo caso, literalmente, pretende que vio un '1') o un expr. – ysth

Cuestiones relacionadas