supresion suma signos resueltos resta parentesis operaciones matematicos matematicas llaves fracciones eliminacion ejercicios ejemplos corchetes con como combinadas agrupacion perl

perl - suma - ¿Por qué los paréntesis son opcionales solo después de la declaración secundaria?



operaciones con parentesis corchetes y llaves (4)

(Asuma el use strict; use warnings; largo de esta pregunta)

Estoy explorando el uso de sub .

sub bb { print @_; } bb ''a'';

Esto funciona como se esperaba El paréntesis es opcional, como con muchas otras funciones, como print, open etc.

Sin embargo, esto causa un error de compilación:

bb ''a''; sub bb { print @_; } String found where operator expected at t13.pl line 4, near "bb ''a''" (Do you need to predeclare bb?) syntax error at t13.pl line 4, near "bb ''a''" Execution of t13.pl aborted due to compilation errors.

Pero esto no:

bb(''a''); sub bb { print @_; }

Del mismo modo, un submarino sin args, como por ejemplo:

special_print; my special_print { print $some_stuff }

Causará este error:

Bareword "special_print" not allowed while "strict subs" in use at t13.pl line 6. Execution of t13.pl aborted due to compilation errors.

Formas de aliviar este error en particular es:

  • Poner y antes el nombre secundario, por ejemplo &special_print
  • Coloque el paréntesis vacío después del nombre secundario, por ejemplo, special_print()
  • Predeclare special_print con sub special_print en la parte superior del script.
  • Llame a special_print después de la declaración secundaria.

Mi pregunta es, ¿por qué este tratamiento especial? Si puedo usar un subtítulo global dentro del guión, ¿por qué no puedo usarlo de la manera que quiera? ¿Hay alguna lógica para sub implementarse de esta manera?

ETA: sé cómo puedo solucionarlo. Quiero saber la lógica detrás de esto.


Creo que lo que te estás perdiendo es que Perl usa un analizador estrictamente de una sola pasada. No escanea el archivo para subrutinas, y luego regresa y compila el resto. Sabiendo esto, a continuación se describe cómo funciona el sistema de análisis de pasaje:

En Perl, la sintaxis sub NAME para declarar una subrutina es equivalente a lo siguiente:

sub name {...} === BEGIN {*name = sub {...}}

Esto significa que la sintaxis sub NAME tiene un efecto de tiempo de compilación. Cuando Perl está analizando el código fuente, está trabajando con un conjunto actual de declaraciones. Por defecto, el conjunto es las funciones integradas. Como Perl ya sabe sobre esto, le permite omitir el paréntesis.

Tan pronto como el compilador golpea un bloque BEGIN, compila el interior del bloque usando el conjunto de reglas actual, y luego ejecuta el bloque inmediatamente. Si algo en ese bloque cambia el conjunto de reglas (como agregar una subrutina al espacio de nombre actual), esas nuevas reglas tendrán efecto durante el resto del análisis.

Sin una regla predeclarada, un identificador se interpretará de la siguiente manera:

bareword === ''bareword'' # a string bareword LIST === syntax error, missing '','' bareword() === &bareword() # runtime execution of &bareword &bareword === &bareword # same &bareword() === &bareword() # same

Al usar estrictas y advertencias como lo ha indicado, las palabras vacías no se convertirán en cadenas, por lo que el primer ejemplo es un error de sintaxis.

Cuando se declara previamente con cualquiera de los siguientes:

sub bareword; use subs ''bareword''; sub bareword {...} BEGIN {*bareword = sub {...}}

Entonces el identificador se interpretará de la siguiente manera:

bareword === &bareword() # compile time binding to &bareword bareword LIST === &bareword(LIST) # same bareword() === &bareword() # same &bareword === &bareword # same &bareword() === &bareword() # same

Por lo tanto, para que el primer ejemplo no sea un error de sintaxis, primero debe verse una de las declaraciones de subrutinas anteriores.

En cuanto al por qué detrás de todo esto, Perl tiene mucho legado. Uno de los objetivos en el desarrollo de Perl fue la compatibilidad hacia atrás completa. Una secuencia de comandos que funciona en Perl 1 todavía funciona en Perl 5. Debido a esto, no es posible cambiar las reglas que rodean el análisis de bareword.

Dicho esto, será difícil encontrar un lenguaje que sea más flexible en la forma en que le permite llamar a las subrutinas. Esto le permite encontrar el método que funcione mejor para usted. En mi propio código, si necesito llamar a una subrutina antes de que haya sido declarada, suelo usar el name(...) , pero si esa subrutina tiene un prototipo, lo llamaré como &name(...) (y tú recibirá una advertencia "subrutina llamada demasiado pronto para verificar el prototipo" si no la llamas de esta manera).


La mejor respuesta que puedo encontrar es que así es como está escrito Perl. No es una respuesta satisfactoria, pero al final es la verdad. Perl 6 (si alguna vez sale) no tendrá esta limitación.

Perl tiene una gran cantidad de crud y cruft de cinco versiones diferentes del idioma. Perl 4 y Perl 5 hicieron algunos cambios importantes que pueden causar problemas con programas anteriores escritos de manera fluida.

Debido a la larga historia, y las diversas formas en que Perl tiene y puede funcionar, puede ser difícil para Perl entender lo que está sucediendo. Cuando tienes esto:

b $a, $c;

Perl no tiene manera de saber si b es una cadena y es simplemente una palabra clave (que fue permitida en Perl 4) o si b es una función. Si b es una función, debe almacenarse en la tabla de símbolos mientras se analiza el resto del programa. Si b no es una subrutina, no debe ponerla en la tabla de símbolos.

Cuando el compilador de Perl ve esto:

b($a, $c);

No sabe qué hace la función b , pero al menos sabe que es una función y puede almacenarla en la tabla de símbolos a la espera de que la definición venga más tarde.

Cuando pre-declara su función, Perl puede ver esto:

sub b; #Or use subs qw(b); will also work. b $a, $c;

y sabe que b es una función. Puede que no sepa lo que hace la función, pero ahora hay una entrada de tabla de símbolos para b como una función.

Una de las razones de Perl 6 es eliminar gran parte del equipaje que queda de las versiones anteriores de Perl y eliminar cosas extrañas como esta.

Por cierto, nunca use Perl Prototypes para evitar esta limitación. Use use subs o predeigne una subrutina en blanco. No uses prototipos.


La razón es que Larry Wall es un lingüista, no un científico de la computación.

Informático : la gramática del lenguaje debe ser lo más simple y clara posible.

  • Evita la complejidad en el compilador
  • Elimina las fuentes de ambigüedad

Larry Wall : las personas trabajan de forma diferente a los compiladores. El lenguaje debe servir al programador, no al compilador. Ver también el esbozo de Larry Wall de las tres virtudes de un programador .


Los paréntesis son opcionales solo si la subrutina ha sido predefinida. Esto está documentado en perlsub .

Perl necesita saber en tiempo de compilación si la palabra clave es un nombre de subrutina o una cadena literal. Si usa paréntesis, Perl adivinará que es un nombre de subrutina. De lo contrario, debe proporcionar esta información de antemano (por ejemplo, utilizando subs ).