Всем привет. Незаметно наступил понедельник и еще чуть менее заметно выходит очередная статья, проливающая свет на Perl 6.
На этот раз пора познакомиться с чем-то более интересным, чем I/O и тому подобное. Вообще, забегая чуть-чуть вперед, скажу, что на этой неделе нас с вами ждут очень интересные открытия из мира Perl 6.
Начнем по возрастающей: «Типы».
Perl 6 является динамическим языком. Это значит, что типы значений переменных распознаются Perl 6 автоматически, без особого участия человека.
Но, в то же время, вы можете использовать типы переменных, если это необходимо именно вам. Например, для того, чтобы отслеживать пользовательский ввод или для чего-нибудь еще.
Все переменные в Perl 6 знают свой тип:
say 42.WHAT; # Int
say "beer".WHAT; # Str
sub answer { return 42 }
say &answer.WHAT; # Sub
Включая ваши собственные классы
class Dog { ... }
my $fido = Dog.new();
say $fido.WHAT; # Pes
Типизированные переменные
Мы можем указывать тип переменных внутри кода:
my Int $x = 42; # OK, 42 isa Int
$x = 100; # OK, 100 isa Int
$x = "CHEEZBURGER"; # Error
Типизированные параметры
Типы передаваемых параметров, например, в функцию, можно указать точно таким же образом:
sub hate(Str $thing) {
say "$name, you REALLY suck!";
}
hate("black hole"); # OK
hate(42); # Type check failure
Существует несколько типов значений, я приведу самые знакомые:
Int — целые, от -inf до inf
Num — вещественные числа
Complex — комплексное число
Str — соответственно, строка
Тип может существовать не только у скаляра, но и у массивов и хешей:
my Int @a;
my Int %h;
В этом случае, подразумевается, что все элементы массива будут соответствовать указанному типу.
Подтипы
Подтипы можно создавать самостоятельно, с помощью ключевого слова subset:
subset PositveInt of Int where { $_ > 0 }
my PositiveInt $x = 5; # OK
$x = -10; # Type check failure
Как и остальные типы данных, подтипы вы можете использовать и внутри собственных функций
Вы можете даже создавать анонимные подтипы прямо на ходу, внутри оъявления переменных:
sub divide(Num $a,
Num $b where { $^n != 0 }) {
return $a / $b;
}
say divide(126, 3); # 42
say divide(100, 0); # Type check failure






































17 августа 2009, 16:06
И как эти ограничения проверяются? По факту (как assert() в Си) или же раньше? То бишь где будет ошибка, если я напишу divide(5,x), -- в divide или нет? "Или нет" значит, что придется доказать, что x != 0 каким-то образом. Типа вот:
divide : forall x in Nat, forall y in Nat != 0 -> exists z in Nat
rule : forall x in Nat != 0 -> exists z in Nat
(где "in" -- принадлежность множеству, forall -- "для всех", exists -- "существует", -> -- импликация)
rule определен как-то так:
rule(x) = 2*x + divide(5,x)
Так как мы знаем, что x != 0 в rule (это одно из предположений), то divide(5,x) делать можно (умозаключение об x передается в divide вместе со значением самой переменной).
В перле так?
> Это значит, что типы значений переменных распознаются Perl 6 автоматически, без особого участия человека.
Миру известен по крайней мере один алгоритм автоматического вывода типов. Аннотации типов не нужны, а типизация все равно статическая. ;)
> $x = "CHEEZBURGER"; # Error
Офигительно. Хочу сильную типизацию в JS. Надеюсь, что и неявное преобразование тоже запрещено? :)
17 августа 2009, 21:13
Очевидно, вто where { ... } — это лексический блок, в котором может находиться при желании все, что угодно: регекспы, интервалы, замыкания, объединения — что угодно.
Например, тип, который может содержать то, что есть в массиве:
my @ary = 1, 2, 3, 4, 5;
subset Ary of Int where { $_ == any @ary }
Или в интервале:
subset Foo of Num where { -5 < $_ < 5 }
17 августа 2009, 21:19