2009-01-23 10 views
51

¿Perl tiene un tipo de enumeración que se adhiere a las mejores prácticas, o tal vez lo más importante, lo necesita?¿Perl tiene un tipo de enumeración?

El proyecto en el que trabajo uno usa cadenas por todos lados para indicar cosas que normalmente usarían un Enum en un lenguaje como C#. Por ejemplo, tenemos un conjunto de números de teléfono en una variedad de hashes, cada uno asociado con un tipo de teléfono ("Inicio", "trabajo", "móvil", etc.):

$phone_number->{type} = 'Home'; 

¿Sería suficiente para usar un conjunto de variables de solo lectura aquí o debería usarse un Enum? He encontrado un enum module on CPAN pero parece usar palabras simples que infringe uno de los Perl Best Practices. Mi forma de pensar sobre el uso de read-only variables es algo como esto:

use Readonly; 

Readonly my $HOME => 'Home'; 
Readonly my $WORK => 'Work'; 
Readonly my $MOBILE => 'Mobile'; 

$phone_number->{type} = $HOME; 

¿Es esta una buena aproximación o hay una mejor manera?

Respuesta

39

No, no hay una construcción enum incorporada. Perl no hace mucha escritura estricta, por lo que creo que en realidad hay poca necesidad de una.

En mi opinión, el enfoque Readonly que utilizó es sólido.

También existe el más tradicional pragma.

use constant { 
    HOME => 'Home', 
    WORK => 'Work', 
    MOBILE => 'Mobile', 
}; 

$phone_number->{type} = HOME; 

Detrás de las escenas, en ella se establece una función para cada constante que devuelve el valor, como tal.

sub HOME() { 'Home' } 

me gustaría seguir con Readonly a menos que desee tomar ventaja de esa propiedad, por ejemplo:

package Phone::Type; 

use constant { 
    HOME => 'Home', 
    #... 
}; 

package main; 

print Phone::Type->HOME, "\n"; 
+0

Para mayor rigurosidad, hay un sub HOME() {'home'} creado detrás de la escena. –

+0

Cuando tiene una subrutina que toma Phone :: Type enum como argumento, ¿cómo se realiza la comprobación dinámica en el argumento de la subrutina? Phone :: Type type enum, no string, not number ... –

+0

Solo para aclarar sub HOME () {'home'} y use la constante { HOME => 'Home', WORK => 'Work', MOBILE => 'Mobile', }; son lo mismo? el último genera (Detrás de la escena) el código? –

8

Su forma es más que suficiente.

También puede crear enumeraciones con Moose :: Util :: TypeConstraints, si está utilizando Moose. (Lo que debería ser).

17

Perl tiene de hecho un tipo de enumeración como en C. Prueba esto para más detalles.

perldoc enum

Por ejemplo:

use enum qw(HOME WORK MOBILE); 

Ahora tenemos:

HOME == 0 
WORK == 1 
MOBILE == 2 

También puede establecer los Indices de sí mismo:

use enum qw(HOME=0 WORK MOBILE=10 FAX); 

Ahora tenemos:

HOME == 0 
WORK == 1 
MOBILE == 10 
FAX == 11 

Mire here para más detalles.

Tenga en cuenta que esto no es compatible con todas las versiones de Perl. Sé que v5.8.3 no lo admite, mientras que v5.8.7 sí lo admite.

+8

En la medida en que puedo decir, 'use enum' es un módulo CPAN, no parte del lenguaje central. –

+0

@paul nathan ... No estoy seguro de que eso impida que alguien lo use. Una gran cantidad de características de perl no son parte del núcleo. –

+0

Todas las otras técnicas fueron un dolor para mí. Tenía un montón de variables y tenía que etiquetar cada una secuencialmente. ENTONCES - mi aplicación externa cambió su formato, requiriendo una definición para ser añadida al COMIENZO de la lista - ¡así tuve que renumerar todo! módulo enum definitivamente era el camino a seguir !! – Brad

2

Siempre debe recordar que PBP es aconsejable, el libro en sí mismo. Necesita interpretar las pautas en lugar de adoptarlas servilmente.

+0

downvoted porque, si bien esto es cierto, también está bastante fuera del tema –

+2

respondiendo a mi propio comentario: me equivoco, esta respuesta no está completamente fuera de tema; es solo decir sarcásticamente lo obvio. una respuesta mejor/más útil discutiría los pros y los contras de las palabras no identificadas y por qué el módulo enum debería o no usarlas. –

+0

no es una cuestión de tema encendido/apagado. esto es un comentario, no una respuesta, por lo que debería haberse ingresado como tal – ysth

5

estoy Perl miedo es completamente parapléjico cuando se trata de estas enumeraciones y constantes con nombre:

  • enumeración y Sólo lectura no son módulos básicos (por lo menos en Perl 5.8, que acabo de comprobar). Por lo tanto, estos pueden no estar disponibles en un sistema donde uno no tiene libertad para instalar nuevos módulos. mientras

    Bareword "FRED" no permitida ":

  • "uso constante" con "utilizar estricta"(que siempre se debe usar) es completamente inutilizable, ya que genera una carga de mensajes de error horribles de la forma Sust. estrictos "en uso

¡Esperemos que hayan resuelto este desastre en Perl 6, si es que alguna vez ve la luz!

+1

Las constantes no imprimen advertencias, y tampoco en 5.8: 'perl -e 'usa terminante qw (subs); use la constante FRED => q {fred}; printf qq {Perl% vd \ nConstant es% s \ n}, $^V, FRED'' da 'Perl 5.8.4 Constant is fred' y no hay advertencias. (Sí, me doy cuenta de que esta respuesta tiene varios años ...) – derobert

0

Esto funcionó muy bien para mí ...

use constant MYENUM => qw(ZERO ONE TWO THREE FOUR); 

BEGIN { 
    eval "use constant (MYENUM)[$_] => $_;" foreach 0..(MYENUM)-1; 
} 

continuación, puede utilizar ZERO, ONE, TWO etc como constantes e imprimir su nombre simbólico utilizando (MYENUM)[$value].

Cuestiones relacionadas