Categories
Posts in this category
- Introduction
- Strings, Arrays, Hashes;
- Types
- Basic Control Structures
- Subroutines and Signatures
- Objects and Classes
- Contexts
- Regexes (also called "rules")
- Junctions
- Comparing and Matching
- Containers and Values
- Where we are now - an update
- Changes to Perl 5 Operators
- Laziness
- Custom Operators
- The MAIN sub
- Twigils
- Enums
- Unicode
- Scoping
- Regexes strike back
- A grammar for (pseudo) XML
- Subset Types
- The State of the implementations
- Quoting and Parsing
- The Reduction Meta Operator
- The Cross Meta Operator
- Exceptions and control exceptions
- Common Perl 6 data processing idioms
- Currying
Sun, 07 Dec 2008
Subset Types
Permanent link
NAME
"Perl 5 to 6" Lesson 21 - Subset Types
SYNOPSIS
subset Squares of Real where { .sqrt.Int**2 == $_ }; multi sub square_root(Squares $x --> Int) { return $x.sqrt.Int; } multi sub square_root(Real $x --> Real) { return $x.sqrt; }
DESCRIPTION
Java programmers tend to think of a type as either a class or an interface (which is something like a crippled class), but that view is too limited for Perl 6. A type is more generally a constraint of what a values a container can constraint. The "classical" constraint is it is an object of a class X
or of a class that inherits from X
. Perl 6 also has constraints like the class or the object does role Y
, or this piece of code returns true for our object. The latter is the most general one, and is called a subset type:
subset Even of Int where { $_ % 2 == 0 } # Even can now be used like every other type name my Even $x = 2; my Even $y = 3; # type mismatch error
(Try it out, Rakudo implements subset types).
You can also use anonymous subtypes in signatures:
sub foo (Int where { ... } $x) { ... } # or with the variable at the front: sub foo ($x of Int where { ... } ) { ... }
MOTIVATION
Allowing arbitrary type constraints in the form of code allows ultimate extensibility: if you don't like the current type system, you can just roll your own based on subset types.
It also makes libraries easier to extend: instead of dying on data that can't be handled, the subs and methods can simply declare their types in a way that "bad" data is rejected by the multi dispatcher. If somebody wants to handle data that the previous implementation rejected as "bad", he can simple add a multi sub with the same name that accepts the data. For example a math library that handles real numbers could be enhanced this way to also handle complex numbers.