uso ejemplo atributo perl attributes

ejemplo - ¿Cómo funcionan los atributos del método Perl?



ejemplo de atributo alt html (3)

Una característica integrada poco conocida de Perl son los atributos. Sin embargo, la documentation oficial está haciendo un trabajo bastante malo al introducir novatos al concepto. Al mismo tiempo, los marcos como Catalyst usan atributos extensivamente, lo que parece facilitar mucho las cosas allí. Como usar algo sin saber las implicaciones es un poco asqueroso, me gustaría saber los detalles. En cuanto a la sintaxis, se parecen a los decoradores de Python, pero la documentación implica algo más simple.

¿Podría explicar (con ejemplos del mundo real, si es posible) para qué sirven los atributos y qué sucede detrás de las puertas?


Los atributos son una de las cosas que si no sabes cómo usarlos, no debes molestarte con ellos. Una vez hice un atributo database_method , para indicarle al sistema que se solicitaría un conjunto de registros antes de ingresar este método y que el método sabía que sus entradas principales vendrían del procedimiento almacenado al que correspondía.

Estaba usando atributos para ajustar las acciones reales y especificadas con esos datos. De modo que una de las ideas realmente útiles es ajustar los métodos con indirección, pero fue más difícil hacer que la persona que llama trabajara, sin anularla. Al final, era demasiado visible como una característica de "solo experto" y habría requerido apoyo para rastrear a través de las entrañas arcanas, algo que desea evitar, si escribe Perl en una tienda perl también.

La gente puede querer rechazarme, pero tomo del artículo citado por Sinan:

Advertencias

Aunque esta es una técnica poderosa, no es perfecta. El código no ajustará adecuadamente las subrutinas anónimas , y no necesariamente propagará el contexto de llamada a las funciones envueltas . Además, el uso de esta técnica aumentará significativamente el número de envíos de subrutinas que su programa debe ejecutar durante el tiempo de ejecución. Dependiendo de la complejidad de su programa, esto puede aumentar significativamente el tamaño de su pila de llamadas. Si la velocidad deslumbrante es un objetivo principal de diseño, esta estrategia puede no ser para usted.

Estos son inconvenientes significativos a menos que esté dispuesto a anular la caller . No me importa tanto la "velocidad deslumbrante", y estoy medio dispuesto a poner mi mano sobre el caller principal para eludir cualquier subrutina que se registre a sí misma como "DO_NOT_REPORT", pero tengo cierta temeridad de codificación que no me ha sucedido. Todavía me han derrotado a mí también.

Incluso el artículo admite cuán documentada está esta característica y contiene esta advertencia. ¿Dime cuándo más ha sido una buena idea usar una característica elegante y oscura? Con frecuencia, la gente termina poniendo el espacio de nombres UNIVERSAL para evitar el problema de la herencia.

(Pero si crees que es una mala respuesta, solo otro voto negativo me dará una insignia de presión de mis amigos: D)


Tiene razón, la documentación no es muy clara en esta área, especialmente porque los atributos no son tan complicados. Si define un atributo de subrutina, como este:

sub some_method :Foo { }

Mientras compila su programa (esto es importante), Perl buscará el submódulo mágico MODIFY_CODE_ATTRIBUTES en el paquete actual o cualquiera de sus clases principales. Se llamará con el nombre del paquete actual, una referencia a su subrutina y una lista de los atributos definidos para esta subrutina. Si este controlador no existe, la compilación fallará.

Lo que hagas en este manejador depende completamente de ti. Si, eso es correcto Sin magia oculta en absoluto. Si desea señalar un error, devolver el nombre de los atributos ofensivos hará que la compilación falle con un mensaje de "atributo no válido".

Hay otro controlador llamado FETCH_CODE_ATTRIBUTES que se llamará cada vez que alguien diga

use attributes; my @attrs = attributes::get(/&some_method);

A este manejador se le pasa el nombre del paquete y la referencia de la subrutina, y se supone que devuelve una lista de los atributos de la subrutina (aunque lo que realmente se hace depende de usted).

Aquí hay un ejemplo para habilitar el "etiquetado" simple de métodos con atributos arbitrarios, que puede consultar más adelante:

package MyClass; use Scalar::Util qw( refaddr ); my %attrs; # package variable to store attribute lists by coderef address sub MODIFY_CODE_ATTRIBUTES { my ($package, $subref, @attrs) = @_; $attrs{ refaddr $subref } = /@attrs; return; } sub FETCH_CODE_ATTRIBUTES { my ($package, $subref) = @_; my $attrs = $attrs{ refaddr $subref }; return @$attrs; } 1;

Ahora, en MyClass y en todas sus subclases, puede usar atributos arbitrarios y consultarlos usando attributes::get() :

package SomeClass; use base ''MyClass''; use attributes; # set attributes sub hello :Foo :Bar { } # query attributes print "hello() in SomeClass has attributes: ", join '', '', attributes::get(SomeClass->can(''hello'')); 1; __END__ hello() in SomeClass has attributes: Foo, Bar

En resumen, los atributos no hacen mucho, lo que los hace muy flexibles: puede usarlos como "atributos" reales (como se muestra en este ejemplo), implementar algo así como decoradores (ver la respuesta de Sinan ), o para su propios propósitos tortuosos.