Нахождение типа данных скалярной переменной в Perl - PullRequest
6 голосов
/ 15 июня 2011

У меня есть функция, которая принимает ввод от пользователя. На входе может быть целое число, число с плавающей точкой или строка. У меня есть три перегруженные функции, которые должны вызываться в зависимости от типа введенных данных. Например, если пользователь вводит целое число (скажем, 100), должна вызываться функция, имеющая целочисленный параметр. Если пользователь вводит строку (скажем, «100»), должна вызываться функция, имеющая строковый параметр.

Так что мне нужно выяснить тип вводимых данных. С помощью регулярных выражений я могу различать целое число и число с плавающей точкой (поскольку мне просто нужно выяснить тип, я не предпочитаю использовать библиотеку, предоставленную на cpan.org), но я не могу понять, как различать целое число из строки. Perl трактует "100" и 100 как одно и то же? Есть ли способ обойти эту проблему?

Ответы [ 4 ]

11 голосов
/ 15 июня 2011

С perldoc perldata:

Скаляры не обязательно одно или другое.Нет места для объявления скалярной переменной типа «строка», типа «число», типа «ссылка» или чего-либо еще.Из-за автоматического преобразования скаляров операциям, которые возвращают скаляры, не нужно заботиться (и фактически не заботиться), ищет ли их вызывающая сторона строку, число или ссылку.Perl - это контекстно-полиморфный язык, скалярами которого могут быть строки, числа или ссылки (включая объекты).Хотя строки и числа считаются практически одинаковыми для почти всех целей, ссылки являются строго типизированными некастабильными указателями со встроенным счетчиком ссылок и вызовом деструктора.

Так что для целочисленных скаляровпросто нужно заранее решить, как вы хотите их обработать.Perl с радостью преобразует число в строку или наоборот, в зависимости от контекста.

9 голосов
/ 15 июня 2011

Perl не делает полезного различия между числами и строковыми представлениями этих чисел. Твой сценарий тоже не должен. Вы могли бы написать некоторый код, чтобы различать вещи, которые выглядят как целые числа и числа с плавающей запятой, но единственный способ узнать, является ли это строкой, это если скаляр не выглядит как целое число или число с плавающей запятой.

Вот простая процедура, которая возвращает int, rat или str в качестве аргумента. Обратите внимание, что 100 и '100' оба int, но что-то вроде 'asdf' будет 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

Поскольку вы работаете над отображением переменных Perl в функции C, вы можете написать что-то вроде этого:

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

Который должен "делать правильные вещи", когда ему дан скаляр Perl. Вы также можете добавить проверку, чтобы убедиться, что аргумент является ссылкой, а затем обработать этот случай по-другому.

2 голосов
/ 15 июня 2011
#!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);

Обман, я знаю ...

Пол

1 голос
/ 15 июня 2011

Рассматривали ли вы передачу функции в качестве ссылки на хеш с клавишами, указывающими тип ввода данных?

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

Вы можете проверить, какой тип вы получили, проверив, какой ключ имеет вход: my $datatype = shift (keys %{$input}) и возьми его оттуда. (Обратите внимание, что неявное разыменование происходит с $input)

switch ($datatype) {
   case string:
       C_string($input->{$datatype});
   case integer:
       C_integer($input->{$datatype});
   case float:
       C_float($input->{$datatype});
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...