Last active
June 7, 2016 13:14
-
-
Save Juerd/b6531810922d0cefec82b650be4915ca to your computer and use it in GitHub Desktop.
Perl 6 types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Types are used as a way to organize behaviour and to guarantee that | |
certain constraints are enforced. | |
=head2 Value types | |
Although every value will invariably be of a single specific type, | |
behaviour can be shared among different types by means of | |
inheritance and composition. Type constraints can be applied to | |
variables, to limit which types of values a variable may hold. | |
A type name used as a function (i.e. by itself or with parentheses) | |
coerces the given value to that type. If no argument is given, it | |
results in the I<type object> for that type: a value that does have a | |
type, but does not have a value. It is said to be I<undefined>. | |
say Int.WHAT; # (Int) | |
say Int.defined; # False | |
say 42.WHAT; # (Int) | |
say 42.defined; # True | |
my $two-digits = Str(42); | |
my $type = Str; | |
say $type.defined; # False | |
my $three-digits = $type(123); | |
say $three-digits.WHAT; # (Str) | |
say $three-digits.defined; # True | |
Type constraints provide I<type safety>: only values of specific types | |
can be used. This can avoid bugs by checking that a variable is used in | |
the way that was intended. The optimizer can sometimes use the type | |
constraint to enable specialized, faster code execution. The nominal | |
type constraint of a variable can be given after the declarator (C<my>, | |
C<our>, C<has>, etc.) and before the name of the variable. Refinements | |
can be declared using C<where> and a value (e.g. a code block) to smart | |
match values against. | |
my Int $number; | |
say $number.WHAT; # (Int) | |
$number = 42; | |
$number = "forty-two"; # Type check failed | |
my Int $small-number where * < 100; | |
$small-number = 50; | |
$small-number = 99; | |
$small-number = 200; # Type check failed | |
A variable declaration without an explicit value assignment will | |
cause the variable to be initialized as the I<type object> of its | |
declared type. | |
my Int $number; | |
say $number.WHAT; # (Int) | |
say $number.defined; # False | |
$number = 42; | |
say $number.defined; # True | |
$number = Int; | |
say $number.defined; # False | |
The specific type refinement constraints of allowing only defined values | |
or only undefined values (that is, type objects), are specified by | |
appending C<:D> or C<:U> to the type name respectively. | |
my Int:D $number = 123; | |
$number = 42; | |
$number = Int; # Type check failed | |
my Any:U $type; | |
$type = Str; | |
$type = Int; | |
$type = 42; # Type check failed | |
The default type constraint for variable declarations is C<Mu>, | |
which will allow values of any type, but initializes as the C<Any> | |
type object. C<Any> inherits from C<Mu>, the root type, and as a | |
type constraint will not hold a C<Junction>. | |
my $foo; | |
my Mu $foo; # Same thing | |
say $foo.WHAT; # (Any) | |
$foo = 3 | 4; | |
say $foo.WHAT; # (Junction) | |
my Any $bar; | |
$bar = 3 | 4; # Type check failed | |
Type constraints for function arguments are similar, except the default | |
will be C<Any> instead of C<Mu>, making the parameter unable to hold | |
a C<Junction>. (If called with a junction, I<autothreading> will occur | |
instead.) | |
sub shout ($message, Int:D :$repetitions = 1) { | |
if ($message.defined) { | |
say $message.uc ~ "!" for 1 .. $repetitions; | |
} else { | |
say "THAT IS A TYPE OBJECT!" for 1 .. $repetitions; | |
} | |
} | |
shout Str; # THAT IS A TYPE OBJECT! | |
shout "Hello, world"; # HELLO, WORLD! | |
shout "Hello, world", :repetitions(3); # three times | |
shout "Hello, world", :repetitions(Int); # Type check failed | |
shout "Hello, world", :repetitions("three"); # Type check failed | |
shout "Hello" & "World"; | |
# Would print either HELLO! WORLD! or WORLD! HELLO!, because | |
# execution order is not defined for autothreading. | |
=head3 Custom value types | |
... | |
=head2 Container types | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think the docs should be using
.^name
when you just want the name, and leave.WHAT
for more advanced usage.( everywhere you have
.WHAT
you also have an invisible.gist
because you are usingsay
)The only reason in my mind to use it here is if you do something like
42.WHAT =:= Int
rather than42 ~~ Int
to say that it is exactly that type.I would like to see at least a passing mention of roles somewhere, especially since you have a variable named
$number
that isn'tNumeric
, but is anInt
.( I think a book about Perl 6 best practices would tell you to type match against roles rather than classes in more places. )
These are just my first thoughts, and following them could result in something more difficult for new Perl 6 programmers, so feel free to ignore me if that is the case. I do like what you have here ignoring my pet peeves.