2011-06-15 4 views
6

Tengo una función que acepta una entrada del usuario. La entrada puede ser un número entero, un flotador o una cadena. Tengo tres funciones sobrecargadas que deben invocarse en función del TIPO DE DATO de los datos ingresados. Por ejemplo, si el usuario ingresa un entero (digamos 100), se debe llamar a la función que tiene un parámetro entero. Si el usuario ingresa una cadena (digamos "100"), debe invocarse la función que tiene el parámetro de cadena.Encontrar el tipo de datos de una variable escalar en Perl

Necesito averiguar el tipo de datos de los datos ingresados. Con las expresiones regulares puedo distinguir entre un número entero y un punto flotante (ya que solo necesito encontrar el tipo, no prefiero usar la biblioteca provista en cpan.org), pero no puedo descifrar cómo diferenciar un entero de una cadena. Perl trata a "100" y 100 como lo mismo? ¿Hay alguna forma de evitar este problema?

+5

Tratar ' "100"' y '100' la misma se considera generalmente una característica de Perl. Necesita explicar mejor por qué es un problema. ¿Qué debería suceder cuando un usuario llama a 'your_function (100)' y cómo debería ser diferente de cuando un usuario llama a 'your_function (" 100 ")'? – mob

+1

Oh ... Pensé en no entrar en los detalles de esto. Pero como la situación lo exige: tengo que llamar algunas funciones C desde dentro de Perl. Las funciones están sobrecargadas y presentes en mi biblioteca. Entonces necesito averiguar el tipo e invocar la versión correcta de la función EXPLICITAMENTE. – letsc

+1

Ignorar mi respuesta [eliminada]. Entendí mal la intención de la pregunta, y no me di cuenta de que estaba hablando de la "entrada" como argumentos físicos para las funciones. – dolphy

Respuesta

11

De perldoc perldata:

escalares no son necesariamente una cosa u otra. No hay lugar para declarar que una variable escalar sea del tipo "cadena", escriba "número", escriba "referencia" o cualquier otra cosa. Debido a la conversión automática de escalares, las operaciones que devuelven escalares no necesitan preocuparse (y de hecho, no pueden importar) si la persona que llama está buscando una cadena, un número o una referencia. Perl es un lenguaje polimórfico contextual cuyos escalares pueden ser cadenas, números o referencias (que incluye objetos). Aunque las cadenas y los números se consideran prácticamente iguales para casi todos los propósitos, las referencias son punteros no categóricos fuertemente tipados con recuento de referencias incorporado e invocación de destructor.

Por lo tanto, para escalas enteras, solo tendrá que decidir de antemano cómo quiere procesarlas. Perl se convertirá alegremente de un número a una cadena o viceversa, según el contexto.

+0

Hmm gracias .. Entonces No debería perder mi tiempo en esto y resolver algún otro enfoque para lidiar con eso ... D – letsc

2
#!perl6 

use v6; 

multi guess (Int $a) { say "got integer: $a" } 
multi guess (Str $a) { say "got string: $a" } 
multi guess (Rat $a) { say "got float: $a" } 

guess(3); 
guess("3"); 
guess(3.0); 

trampa, lo sé ...

Paul

+0

suena genial !! Definitivamente lo intentaré. Por casualidad, cualquiera de estas opciones o cualquier otra alternativa con la versión 5? – letsc

+0

No estoy enojado. No creo que veamos un tipado fuerte en Perl5 pronto ... – pavel

9

Perl no hace una distinción útil entre los números y representaciones de cadena de esos números. Tu script tampoco debería. Podría escribir un código para diferenciar entre cosas que parecen enteros y flotantes, pero la única forma de saber si se trata de una cadena es si el escalar no parece un entero o un flotador.

Aquí hay una rutina simple que devolverá int, rat, o str para su argumento. Tenga en cuenta que 100 y '100' son ambos int, pero algo así como 'asdf' será str.

use Scalar::Util 'looks_like_number'; 
sub guess_type { 
    looks_like_number($_[0]) ? $_[0] =~ /\D/ ? 'rat' : 'int' : 'str' 
} 

say guess_type 1;  # int 
say guess_type "1"; # int 
say guess_type 1.1; # rat 
say guess_type 'asdf'; # str 

Puesto que usted está trabajando en las variables de Perl mapeo de funciones C, se podría escribir algo como esto:

sub myfunction { 
    if (looks_like_number($_[0]) { 
     if ($_[0] =~ /\D/) {C_float($_[0])} 
     else    { C_int($_[0])} 
    } 
    else {C_string($_[0])} 
} 

cual debería "hacer lo correcto" cuando se le da un escalar Perl. También puede agregar un cheque para ver si el argumento es una referencia, y luego manejar ese caso de manera diferente.

+0

No estoy de acuerdo con esto en absoluto: "Tu script tampoco debería". El hecho de que un idioma no haga algo no implica que hacer eso siempre esté mal. – Anthony

1

¿Ha considerado pasar la función una referencia hash con las teclas que indican qué tipo de datos es la entrada?

my $str_input = { string => "100" }; 
my $int_input = { integer => 100 }; 
my $float_input = { float => 100.0 }; 

Puede comprobar qué tipo tienes, al comprobar qué tecla de entrada tiene: my $datatype = shift (keys %{$input}) y tomar desde allí. (Nota del desreferenciar implícita pasando a $input)

switch ($datatype) { 
    case string: 
     C_string($input->{$datatype}); 
    case integer: 
     C_integer($input->{$datatype}); 
    case float: 
     C_float($input->{$datatype}); 
} 
Cuestiones relacionadas