2010-08-03 15 views
19

A partir de Perl 5.10, ahora es posible analizar léxicamente la variable de contexto $_, explícitamente como my $_; o en una construcción given/when.

¿Alguien ha encontrado buenos usos del léxico $_? ¿Hace que las construcciones sean más simples/seguras/más rápidas?

¿Qué pasa con las situaciones que lo hacen más complicado? ¿El léxico $_ ha introducido algún error en su código? (dado que las estructuras de control que escriben en $_ usarán la versión léxica si está dentro del alcance, esto puede cambiar el comportamiento del código si contiene alguna llamada de subrutina (debido a la pérdida del alcance dinámico))

Al final, Me gustaría construir una lista que aclare cuándo usar $_ como léxico, como global, o cuando no importa en absoluto.


NB: como de perl5-5.24 estas características experimentales son no longer part of perl.

+0

Creo que la respuesta a su pregunta es en su mayoría cubierto [aquí] (http://stackoverflow.com/questions/3393038/does-my-do-anything-if-is-implied) en la respuesta a mi pregunta. – xenoterracide

+0

@xenoterracide => La respuesta allí ciertamente cubre algunos de los aspectos del léxico '$ _', pero no todos. Eso es lo que me gustaría cubrir aquí. –

+0

Lo sé, pero también podría tener un buen lugar para empezar;) – xenoterracide

Respuesta

8

IMO, una gran cosa para salir de léxico $_ es el nuevo prototipo _ símbolo.

Esto le permite especificar una subrutina para que tome un escalar o si no se proporciona ninguna, tomará $_.

Así que en lugar de escribir:

sub foo { 
    my $arg = @_ ? shift : $_; 

    # Do stuff with $_ 
} 

me puede escribir:

sub foo(_) { 
    my $arg = shift; 

    # Do stuff with $_ or first arg. 
} 

No es un gran cambio, pero es sólo que mucho más simple cuando quiero que el comportamiento. La remoción repetitiva es algo bueno.

Por supuesto, esto tiene el efecto de knock-on de cambiar los prototipos de varios builtins (por ejemplo, chr), lo que puede romper un poco el código.

En general, doy la bienvenida a léxico $_. Me da una herramienta que puedo usar para limitar el munging de datos accidentales y las interacciones extrañas entre funciones. Si decido usar $_ en el cuerpo de una función, al lexicalizarlo, puedo estar seguro de que cualquier código que llame, $_, no se modificará en el código de llamada.

El alcance dinámico es interesante, pero en su mayor parte quiero un alcance léxico. Agregue a esto las complicaciones alrededor de $_. He escuchado terribles advertencias sobre la inconveniencia de simplemente hacer local $_;, que en su lugar es mejor usar for ($foo) { }.Lexicalized $_ me da lo que quiero 99 veces de cada 100 cuando he localizado $_ por cualquier medio. Lexical $_ hace una gran conveniencia y la característica de legibilidad más robusta.

La mayor parte de mi trabajo ha tenido que trabajar con Perl 5.8, por lo que no he tenido la alegría de jugar con el léxico $_ en proyectos más grandes. Sin embargo, se siente como que esto hará un largo camino para hacer que el uso de $_ sea más seguro, lo cual es algo bueno.

+2

¿Qué razones se han dado para 'for ($ foo) {...}' en lugar de 'local * _ = \ $ foo;'? Según mi experiencia, este último es un poco más rápido (ya que no tiene que configurar un alcance y un iterador para la lista de elementos únicos), pero me interesaría saber si hay algún problema de seguridad que deba tenerse en cuenta. –

+1

Eric, fui a buscar la referencia específica hoy y no pude encontrarla. Todo lo que puedo recordar en este punto es una advertencia contra el 'local $ _' proveniente de" una persona cuya opinión respeto "en algún momento a mediados de 2009. Entonces, a menos que pueda fundamentar mejor el reclamo, mejor ignórelo como nada más que rumores. El reclamo fue que la localización no cubría todos los casos extremos con el '$ _' especial. Nunca encontré un informe de error o un caso de prueba para respaldar la advertencia. – daotoad

0

No he tenido ningún problema aquí, aunque tiendo a seguir algo de una política de "No preguntar, no decir" cuando se trata de la magia de Perls. Es decir. las rutinas no son , por lo general, se espera que dependa de sus pares que atornillan datos no léxicos como efecto secundario, ni los permite.

He probado el código contra varias versiones 5.8 y 5.10 de perl, mientras uso un 5.6 que describe Camel para referencia ocasional. No he tenido ningún problema La mayoría de mis cosas fueron hechas originalmente para Perl 5.8.8.

3

Una vez encontré un issue (error sería demasiado fuerte) que surgió cuando estaba jugando con el módulo Inline. Este script sencillo:

use strict qw(vars subs); 
for ('function') { 
    $_->(); 
} 
sub function { 
    require Inline; 
    Inline->bind(C => <<'__CODE__'); 
void foo() 
{ 
} 
__CODE__ 
} 

falla con un mensaje de error Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380.. En el interior del módulo Inline se encuentra una subrutina que quería modificar $_, lo que lleva al mensaje de error anterior.

Usando

for my $_ ('function') { ... 

o no declarar my $_ es una solución viable a este problema.

(El módulo Inline se corrigió para solucionar este problema en particular).

1

[Justificación: Una breve respuesta adicional con un resumen rápido de los recién llegados perl que pueden estar pasando. En la búsqueda de "tema léxico perl", uno puede terminar aquí.]

Por ahora (2015) Supongo que es de conocimiento común que la introducción del tema léxico (my $_ y algunas características relacionadas) llevó a algunos difíciles de detectar en los comportamientos involuntarios iniciales así que era marked como experimental y luego ingresado en un deprecation stage.


resumen parcial de#RT119315: Una de ellas fue por algo así como use feature 'lextopic';to make use of a new lexical topic variable: $^_. Otro punto destacado es que un "implicit name for the topicalizing operator ... other than $_" funcionaría mejor si se combina con funciones explícitamente léxicas (, por ejemplo, léxica map o lmap). No está claro si estos enfoques permitirían de alguna manera rescatar given/when. En el más allá de las fases experimentales y de depreciación, tal vez algo pueda terminar viviendo en el río del CPAN.