Assuming roles
Published: 2017-12-21 18:07:27

---
title: Assuming roles
published: True
description: Grammars in Perl6 are classes. We will see how they use roles to componentize parsing. 
tags: 
---

![Mariano does Chavo del Ocho, graffiti in Granada](https://thepracticaldev.s3.amazonaws.com/i/ujoi0wca6qamrrkmmlx4.jpg)
I have seen many texts talking about object orientation use ontological metaphors. A Lamborghini is a car is a vehicle. Not bad, as metaphors go, but it pins you to a hierarchical structure where you refine until you obtain what you want and if you want to mix stuff, and have say a flying car, you have sometimes to graft two ontological trees together in a way that is not pleasant to any of them.
Fortunately, modern object oriented programming, while following that general structure, does allow for more modern, component based, classes. These components are generally called [mixins](https://en.wikipedia.org/wiki/Mixin), but also roles, modules, interfaces or traits. Want a flying car? Grab a Trabbi, duck-tape some kites, and here you go!

## Many modern languages include these mixins.

Ruby, for instance, calls them [modules](http://ruby-doc.com/docs/ProgrammingRuby/html/tut_modules.html). We might want, as [we](https://dev.to/jj/matching-things-with-perl-6-grammars-ao9) [have](https://dev.to/jj/introduction-to-grammars-with-perl6-75e) [done](https://dev.to/jj/matching-with-match-ima), to describe text using these classes

```Ruby
#!/usr/bin/env ruby

module Words
  attr :words
  def to_string( ligature ) 
    return @words.join(ligature)
  end
end

class Paragraph
  include Words
  
  def initialize(words)
    @words = words
  end
  
  def to_string()
    return "\n"+@words.join(" ")+"\n"
  end
end

sentence = Paragraph.new("these are the words".split(/\s+/))
puts sentence.to_string()
```

Text things include words, so we define `Words` to contain them. And we define it as `module` to indicate this is not a complete thing, but only a component that, Lego-like, starts to make sense once it has been included in a full-fledged `Class`, like the one below, which does `include Words` at the beginning and then directly uses the component-defined variable, `@words` to initialize it and to print stuff. Really not groundbreaking thing, which in this case, besides, could maybe be used via inheritance, but actually a `Paragraph` `is-not-a` `Words`, so we're ontologically safe here and besides have created a simple component which can be tested and managed independently. 

## And Perl6 also includes mixins.

Only it calls them [roles](https://perl6advent.wordpress.com/2009/12/18/day-18-roles/), but they are pretty much the same. Let's see how this thing works:

```Perl6
#!/usr/bin/env perl6

# Thanks to https://perl6advent.wordpress.com/2009/12/18/day-18-roles/
role Words {
    has @.words;
    method to-string( Str $ligature ) {
	return @!words.join( $ligature );
    }
}

class Paragraph does Words {

    submethod BUILD( :@!words ) {
    }
    
    method to-string() {
	return "\n" ~ self.Words::to-string( " " ) ~ "\n";
    }
}

my $sentence = Paragraph.new(words => "these are the words".split(/\s+/));
say $sentence.to-string();
```
Except for the fact that we need explicit declaration of `@.words`, in this case as a public variable, which can be automatically retrieved from objects using simply `words`, it's pretty much the same as the Ruby one, I know, down to the `@`, which Ruby took from Perl5, by the way. Perl6 uses the keyword `has` to declare variables, as in *this role has words*. Perl6, the language you can read aloud. Unlike Ruby, the twigil used for declaration (`@.`) becomes `@!` when you actually use it inside the object. Why? Well, this generation is kind of self-focused to the point that they make an exclamation when dealing with themselves. Self → `!`, with the `@` in front to indicate that we're dealing with some array-like thing. We use also `Str ligature` to declare the signature of the `to-string` method; it will error if we use it otherwise, and as well it should, since non-stringy data would not make a lot of sense.

But roles are made to be played, and `Paragraph` does `Words`. However, this is a class and we have to assign values to the instance variables in the constructor, which is a `submethod` in Perl6. Submethods cannot be inherited, you cannot really inherit the constructor which is called `BUILD` in this language, right? Every object has got its own little way to bootstrap itself into existence; however, since this paragraph does words, just mentioning the variable we will intialize is enough to generate the assignment code. `:@!words` is shorthand for *we are going to initialize the `@!words` variable using a hash* (thus the `:`) with the key `words`. This is what we do later on:

```Perl6
my $sentence = Paragraph.new(words => "these are the words".split(/\s+/));
```
`splits` does split using a regular expression

> Which we saw briefly in [this post](https://dev.to/jj/matching-with-match-ima) of the same "Grammars are my friends" series.

giving an array of words, which is what `@!words` actually wants. But we need to use the `to-string` method, which is named exactly the same as the one in the `Role`. No sweat:

```Perl6
return "\n" ~ self.Words::to-string( " " ) ~ "\n";
```

`self.Words` will extract the *Wordy* part of the Paragraph and use that particular `to-string`, not the one here, provoking an interminable loop that would gobble up the whole universe.  `~` in this case concatenates

> Also stringifies. We'll return to that role later on in the series.

We can define a different *client* for our Role:
```Perl6
class Heading does Words {

    submethod BUILD( :@!words ) {
    }
    
    method to-string() {
	return "\n<h1>" ~ self.Words::to-string( " " ) ~ "</h1>\n";
    }
}
```

Which is pretty much the same, except it returns a level-1 HTML heading. 

## Lots of things we can do with this

But we were talking about [Grammars](https://dev.to/jj/introduction-to-grammars-with-perl6-75e). [Grammars in Perl6 are actually classes](https://www.reddit.com/r/perl6/comments/7ezrz7/ive_written_a_small_bbc_news_scraper_in_perl_6/dqfegsr/).

So the more we know about them, the better. We'll get happily back to grammars very soon.