Raku is a gradually typed language which means a variable can be either untyped or typed. If untyped, the variable can store data of different types. If typed, the variable can only store values of that type. In Raku, a type defines a new object by creating a type object that provides an interface to create instances of objects or to check values against.
Raku is also object oriented to the core and there is a class (or role) for any construct you might find yourself working with. Some of the most commonplace types are:
Str
for string of characters.Int
for integer (arbitrary-precision).UInt
for unsigned integer (arbitrary-precision).Rat
for rational number (limited-precision).Num
for floating-point number.Complex
for complex numbers.Bool
for boolean values.Sub
for subroutines.Signature
for the parameter list patternCapture
for argument list suitable for passing to a Signature
.Nil
for absence of a value or a benign failure.say 12; # Int
say 'Hi'; # Str
say ½; # Rat
say 12.5; # Rat
say 2e0; # Num
say 3+i; # Complex
say sub { "Hi" }(); # Sub
say True # Bool
$ perl6 type01.p6
12
Hi
0.5
12.5
2
Hi
True
One way of declaring a variable of a certain type is to place the type between
the declarator (my
, our
, etc.) and the variable name:
my Str $person = "Heya";
my Int $age = 25;
say "Name: ", $name;
say "Age: ", $age;
# Assigning a different type will cause a type check failure at runtime
$person = 23;
$ perl6 type02.p6
Name: Heya
Age: 25
Type check failed in assignment to $person; expected Str but got Int (23)
To find out the type of an object, use the .^name
method on the object:
my $greet = "Hi";
my $num = 2;
my $bool = True;
say $greet.^name; # returns `Str`, the type of the string 'Hi'
say $num.^name; # returns `Int`, the type of the integer 2
say $bool.^name; # returns `Bool`, the type of the boolean True
say 'Hi' ~~ Str; # smartmatching against a type
say 'Hi' ~~ Int; # same as above
$ perl6 type03.p6
Str
Int
Bool
True
False
Smartmatching (through the ~~
operator) against a type smiley (either :D
for defined values or :U
for undefined values) will let you know if a particular
invocant is a type object (:U
) or an instance object (:D
) of a certain type.
The default type smiley is :_
.
say 2 ~~ Int:D; # `True` because 2 is an instance of the `Int` type
say 2 ~~ Int:U; # `False` because 2 isn't a type object
say Int ~~ Int:D; # `False` because `Int` isn't an instance object
say Int ~~ Int:U; # `True` because `Int` is type object
say 2 ~~ Int:_; # same as `2 ~~ Int:U`
say Int ~~ Int:_; # same as `Int ~~ Int:U`
# Similarly, the `.DEFINITE` method can be used to test for
# the definedness of an object.
say "I am string".DEFINITE; # returns `True` because it's an instance object
say Str.DEFINITE; # returns `False` because it's an type object
$ perl6 type04.p6
True
False
False
True
True
True
True
False
To subtype a given type, use the subset
keyword. To apply further
constraints to the subtype, append the where
clause with a constraint.
# A `BigInt` is type object that defines a number
# greater than a million.
subset BigInt of Int where { $_ > 1_000_000 };
say 1_000_001 ~~ BigInt;
say 100 ~~ BigInt;
# An `Exclamation` is a type object that defines a string
# containing at least an exclamation mark.
subset Exclamation of Str where *.contains('!'); # using the Whatever Star
# instead of a block
say "Hello" ~~ Exclamation;
say "Hi!!!" ~~ Exclamation;
$ perl6 subset.p6
True
False
False
True
To declare an enumeration of constant key-value pairs with an associated
type, use the enum
keyword.
enum Direction <East North South West>;
say Direction.enums;
my $alaska = North;
say $alaska ~~ Direction;
say $alaska;
say "Type: ", $alaska.^name;
say "Value: ", $alaska.value;
# Operations can be performed with the names since increasing
# integer values, starting at 0, are assigned to each name.
say "Sum: ", East + South + West + North;
$ perl6 enum01.p6
Map.new((East => 0, North => 1, South => 2, West => 3))
True
North
Type: Direction
Value: 1
Sum: 6
If the values are meaningful, they can be specified explicitly.
enum Shape (Triangle => 3, Square => 4, Pentagon => 5);
say Shape.enums;
say Triangle ~~ Shape;
say Triangle.^name;
say Triangle.value;
# Values need not be integer values.
enum TrafficLight ( Red => "Go", Green => "Go", YELLOW => "SLOW DOWN" );
say "-" x 15;
say Red ~~ TrafficLight;
say Red.value;
$ perl6 enum02.p6
Map.new((Pentagon => 5, Square => 4, Triangle => 3))
True
Shape
3
---------------
True
Go
For more info, go to
- https://docs.perl6.org/type.html to find a list of available types
- https://docs.perl6.org/language/typesystem