¿Hay alguna manera de usar una "constante" como clave hash en Perl?


¿Hay alguna forma de usar una constante como clave hash?

Por ejemplo:

use constant X => 1;

my %x = (X => 'X');

El código anterior creará un hash con "X" como clave y no 1 como clave. Considerando que, quiero utilizar el valor de la constante X como clave.

Author: Jagmal, 2008-09-19

9 answers

use constant en realidad hace subrutinas constantes.

Para hacer lo que quieras, necesitas llamar explícitamente al sub:

use constant X => 1;

my %x = ( &X => 'X');

O

use constant X => 1;

my %x = ( X() => 'X');
 44
Author: nohat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 20:57:00

Otra opción es no usar la constante use pragma y flip para leer solo según las recomendaciones en las Mejores Prácticas de Perl de Damian Conway.

Cambié hace un tiempo después de darme cuenta de que las referencias de hash constantes son solo una referencia constante al hash, pero no hago nada sobre los datos dentro del hash.

La sintaxis readonly crea variables de "aspecto normal", pero en realidad impondrá la constante o readonlyness. Puedes usarlo como lo harías con cualquier otro variable como clave.


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

 19
Author: shelfoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 21:11:07

Tu problema es que => es una coma mágica que automáticamente cita la palabra delante de ella. Así que lo que escribiste es equivalente a ('X', 'X').

La forma más sencilla es usar una coma:

my %x = (X, 'X');

O bien, puede agregar varios signos de puntuación para que ya no tenga una palabra simple frente a=>:

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
 14
Author: cjm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 21:05:56

Use $hash{CONSTANT()} o $hash{+CONSTANT} para evitar que el mecanismo de entrecomillado de bareword se active.

De: http://perldoc.perl.org/constant.html

 9
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-12 01:03:58

La mayoría de las otras personas han respondido bien a su pregunta. Tomados en conjunto, estos crean una explicación muy completa del problema y soluciones recomendadas. El problema es que el pragma de Perl" use constant " realmente crea una subrutina en su paquete actual cuyo nombre es el primer argumento del pragma y cuyo valor es el último.

En Perl, una vez declarada una subrutina, puede ser llamada sin paréntesis.

Entendiendo que las "constantes" son simplemente subrutinas, puede ver por qué no están interpolados en cadenas y por qué el operador" fat comma ""= > " que cita el argumento de la izquierda piensa que le has entregado una cadena (prueba otras funciones integradas como time () y keys () en algún momento con la coma fat para mayor diversión).

Afortunadamente, puede invocar la constante usando puntuación explícita como paréntesis o el sello ampersand.

Sin embargo, tengo una pregunta para usted: ¿por qué está usando constantes para las claves hash?

Se me ocurren algunas escenarios que podrían conducirte en esta dirección:

  1. Quieres controlar qué claves pueden estar en el hash.

  2. Desea abstraer el nombre de las claves en caso de que estas cambien más tarde

En el caso del número 1, las constantes probablemente no guardarán tu hash. En su lugar, considere crear una Clase que tenga setters y getters públicos que llenen un hash visible solo para el objeto. Esta es una solución muy un-Perl como, pero muy fácilmente a hacer.

En el caso del número 2, todavía abogaría fuertemente por una Clase. Si el acceso al hash está regulado a través de una interfaz bien definida, solo el implementador de la clase es responsable de obtener correctamente los nombres de las claves hash. En cuyo caso, no sugeriría usar constantes en absoluto.

Espero que esto ayude y gracias por su tiempo.

 6
Author: jjohn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-03 15:29:30

El use constant pragma crea una subrutina prototipada para no tener argumentos. Mientras que se ve como una constante de estilo C, en realidad es una subrutina que devuelve un valor constante.

El => (coma fat) entrecomilla automáticamente el operando izquierdo si es una palabra a pelo, al igual que la notación{hash {key}.

Si su uso del nombre de la constante se parece a una palabra a pelo, los mecanismos de comillas se activarán y obtendrá su nombre como clave en lugar de su valor. Para evitar esto, cambie el uso para que no sea una palabra pura. Por ejemplo:

use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;

En los inicializadores, también puede usar la coma simple en su lugar:

%hash = (X, 1);
 5
Author: Michael Carman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 21:16:26

=> el operador interpreta su lado izquierdo como una "cadena", como lo hace qw ().

Intenta usar

my %x = ( X, 'X');
 2
Author: Arkadiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 20:58:17

Una forma es encapsular X como (X):

my %x ( (X) => 1 );

Otra opción es eliminar '= > 'y usar', ' en su lugar:

my %x ( X, 1 );
 2
Author: Frosty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 20:58:25

Comentario @ shelfoo (la reputación no es lo suficientemente alta como para agregar comentarios directamente allí todavía!)

Totalmente de acuerdo sobre las Mejores Prácticas de Perl por Damian Conway... su lectura muy recomendable.

Sin embargo, por favor lea Comentario de Recomendación del Módulo PBP que es una "errata" útil si planea usar PBP para una guía de estilo interna.

 1
Author: draegtun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-21 15:01:21