Perl6 Multi Method Signatures : Self Introspection
Tags: perl6
Published: 2018-01-17 17:04:10

---
title: "Perl6 Multi Method Signatures : Self Introspection"
published: true
description: A small note on Perl6 multi methods    
tags: perl6
---
# Perl6 Multi Method Signatures : Self Introspection

I am a big fan of Perl6. One of it's more powerful features are multi subs (and methods) that allow you to handle calls in different ways based on the signature of the call. 

Whilst a number of languages have the ability to do multi dispatch Perl6 not only can perform dispatch on the number of arguments or their types it can also choose which code path to follow based on the arguments values. For instance there's the classic Factorial as a recursive multi sub.


```perl6
multi sub fac(0) { 1 }
multi sub fac(UInt $f where $f > 0) { $f * fac($f-1) }

```

Here we define two code paths. One where you call the sub with 0 and another where you call it with an unsigned integer greater than 0. That's great but what if you have an object and want to process method calls differently based on the objects field values? 

For example you have the following method:

```perl6
method retrieve-archived-data() {   
    # This won't work if our object has not be archived yet.
    # Fail this call
    fail "Can't Retrieve Data for an object that's never been archived" 
        unless $.archived;

    # Code here that gets archived data from some source. 
    # It takes a while and the above check was added because it used to take a 
    # while and then fail.
}

```

So at some point this method would take a lot of time looking for the archived data and then fail if it had never been archived. So our intrepid developer put a check in at the top the script to avoid that. The problem with that sort of thing is it soon mounts up. It'd be nice to be able to make it a multi method but how? The $ variable isn't in the signature. 

Simple. We add it! 

Normally when you call an object method the object you call it on is avaliable in the method as `self` or `$`. But you can also give it a different name to use with the method as well for example:

```perl6
method set-name( $pet : $name ) {
    $pet!name = $name
}
    
```

Note that we separate the object name and the rest of the arguments with a `:` instead of a `,` as normal. Like other arguments we can add a `where ` clause between the name and the seperator. With this knowledge we can rewrite our method:


```perl6
multi method retrieve-archived-data( $ where ! $.archived: ) {
    # This won't work if our object has not be archived yet.
    # Fail this call
    fail "Can't Retrieve Data for an object that's never been archived";
}

multi method retrieve-archived-data() {
    # Code here that gets archived data from some source. 
}

```

Note the trailing `:` if you miss that out it isn't going to work.

In this way we can remove a lot of the special cases that often pepper method that have been around for a while. Keeping our code lean and easy to read.

I hope you found that interesting. I'm hoping to write some more posts here about Perl6 and why I think that it's well worth some of your time. 

## Note

I've updated the second example to remove the redundant second check. I should also mention that `$` is the anonymous scalar variable (when it's used in the signature). When you are in a method `$.foo` is another way of saying `self.foo`. 

You can, if you want, name a variable to reference inself of `self` eg:

```
method named-access( $name: ) {
    $name.field;
}

```
In this method `$name.field`, `self.field` and `$.field` will all reference the same object.

Sorry for any confusion.