Pull to refresh

Perl6 — Работа с типами данных

Reading time 2 min
Views 3.2K
До сих пор в статьях было лишь поверхностное упоминание о типах данных — объявление переменной определенного типа, либо указание результата операции, но все что мы могли, это лишь терпеть выходки компилятора — «хочу умру (die), захочу варнинг кину, или просто поменяю тип».
Собственно, для тех кто хочет почувствовать себя богом хоть как-то важным в управлении типами в своем же скрипте, добро пожаловать под кат.


Итак, допустим мы написали функцию, которая принимает в качестве параметров две переменные:
sub Func($a, $b) {...}


И нужно нам, чтобы функция отрабатывала всегда одним образом, но если вдруг будут переданы в качестве параметров дробное число и строка, или же наоборот, то выполнить другие действия.

Начнем с малого — узнаем какой у нас тип данных у каждой из переменной, для этого используем метод WHAT, который вернет type object — объект обозначающий тип данных (например для значения 10 будет возвращен объект "(Int)" ). Следует отметить, что возвращается именно объект, а не строка, и простое сравнение двух типов через, например, == или eq не подойдет. Для того чтобы сравнить полученный объект с типом мы воспользуемся оператором умного сравнения '~~':
sub Func($a, $b)
{
 $condition = ( ($a.WHAT ~~ (Rat)) ?& ($b.WHAT ~~ (Str)) );
 $condition ?|= ( ($a.WHAT ~~ (Str)) ?& ($b.WHAT ~~ (Rat)) );
 if ($condition)
  {
     #`(SomeWork)
  }
 else
  {
    #`{AnotherWork}
  }
}

(Rat) и (Str) являются type object'ами действительных чисел и строк соответственно.
Для тех кто уже подзабыл ?& — Логическое «И», ?| — Логическое «ИЛИ».

И так, мы научились определять тип значения переменной, и взависимости от него выполнять какие либо действия. Но давайте посмотрим, в каких именно случаях это делать необходимо:
my Int $a;
sub Func($p)
{
  $a = $p;
}

Func(10);
Func("Test");

В нашем случае, скрипт умирает когда пытается переменной, которая может содержать только целые числа, присвоить строку.

Подкорректируем немного наш пример, и напишем следующее:
  $a = +($p);

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

Попытаемся использовать следующую конструкцию:
  $a = Int($p);

Уже лучше, так как если мы передадим число типа (Rat), то оно будет преобразовано к типу (Int), но вот если мы передадим строку, то получим уже ошибку преобразования строки в число, а именно о том, что строка должна иметь вид числа в 10-ой системе счисления.
Пока что я нашел только один способ заставить скрипт работать дальше — отлов исключений. На мой взгляд это самое логичное действие, но об этом мы поговорим в следующих статьях

Также наш скрипт может умереть если функция попытается вернуть значение, несоответствующее описанию:
sub Func($p) of Int
{
  return $p;
}
Func("test");

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

На последок хочу сказать, что по моему мнению ограничения на типы хранимых данных может сильно помочь в описании «интерфейсов» функций, и дают некоторые плюсы типизированных языков программирования.
Надеюсь эта информация была полезной.
Tags:
Hubs:
+9
Comments 6
Comments Comments 6

Articles