Quick Tip #9: User-defined data types

Perl 6 has “gradual typing”. I can constrain values when I like, and let them run free otherwise. User-defined data types are one of the Perl 6 features that excite me the most. I can define what sort of value I can put in a container thingy, and I can define my own types any way that I like.

First, I’ll show a couple of built-in types. I can constrain an array to contain only Int values. I place the type between the declarator and the variable name. If every value I want to store is that type, I have no problem. If there’s a non-decimal integer string (say, a hex digit), I have a problem:

$ perl6
To exit type 'exit' or '^D'
> my Int @array = < 1 2 3 >
[1 2 3]
> my Int @other_array = < 8 9 a b >
Type check failed in assignment to @other_array; expected Int but got Str ("a")

This means I can constrain some thing at the point I store them in the variable instead of checking a type-agnostic array every time I use it somewhere else.

Perl 6 already comes with some classes. The Int type is a platform-agnostic number that doesn’t depend on the local ideas of integers. I could use the lowercase version, int, to specify a native type. Those are limited to the storage types on the platform:

> my Int $j = 99999999999999999999
99999999999999999999
> my int $j = 99999999999999999999
Cannot unbox 67 bit wide bigint into native integer

I can make my own type. I can create my own classes and then use those class names as types:

> class Butterfly {}
(Butterfly)
> my Butterfly $thingy1 = Butterfly.new
Butterfly.new
> my $animal = Butterfly.new
Butterfly.new
> $animal.WHAT
(Butterfly)
> my Butterfly $thingy2 = $animal
Butterfly.new
> my Butterfly $thingy3 = 137
Type check failed in assignment to $thingy3; expected Butterfly but got Int (137)

Check that out! I didn’t put anything in the class, but Perl 6 provided the new constructor for me. I’ll write about that some other time.

I can create subtypes based on those that already exist. First, the
value has to satisfy the base type, then the extra constraint I put on it. I use subset to start it off and a where clause with some code:

> subset Vowel of Str where *.lc ∈ set( <a e i o u y m> )
(Vowel)
> my Vowel $s = 'A';
A
> my Vowel $s = 'e'
e
> my Vowel $s = 'j'
Type check failed in assignment to $s; expected Vowel but got Str ("j")

In this case, I created a new type called Vowel based on Str. The value has to be some sort of string, so thats a start, but I constrain it to be a string in a set (which I wrote about yesterday in Perl 6 sets).

Zoffix has a very good post, “Perl 6 Types: Made for Humans” on the same thing, and Brad Clawsie created Subsets::Common to comprise interesting types. A StackExchange question on gradual typing is very interesting as well, although it has virtually nothing to do with Perl 6. Jonathan
Worthington has an older presentation on types from YAPC::EU 2008.

Leave a Reply

Your email address will not be published. Required fields are marked *