Собственно, для тех кто хочет
Итак, допустим мы написали функцию, которая принимает в качестве параметров две переменные:
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");
Так что в данном случае, тоже не помешало бы сделать проверку выходных значений.
На последок хочу сказать, что по моему мнению ограничения на типы хранимых данных может сильно помочь в описании «интерфейсов» функций, и дают некоторые плюсы типизированных языков программирования.
Надеюсь эта информация была полезной.
ссылка на оригинал статьи http://habrahabr.ru/post/190266/
Добавить комментарий