Durations vs Roles

So, I patched in some dodgy but working for this example code to handle the duration of notes. And then I started to think about how to do it properly.

About half of the musical elements in an ABC tune have a duration. So my first thought was, oooo, define an ABC::Duration role! I was excited, because this seemed like the first really good example I’d seen in my own work of where a role was appropriate and seemed superior to class inheritance.

So I started out defining a duration role with a Real attribute for its length, and two new methods, one which took a Real, and one which took the parsed bits of the note_length regex as strings. But then I started thinking about what that meant. If you define a class which does a role, how do you call that role’s new method? If I’m building up the AST, I’m going to want to create a duration before I have an element to attach it to — how do you build an element around an existing duration? And half of the objects which have durations are perhaps not best represented using a stored duration value — for instance, a triplet element’s duration is the total duration of its three wrapped notes, times 2/3 — making the stored duration value redundant.

So, this is one of those posts which I make before I’ve figured out what the answer is. I’ve verified that you can create a standalone role object in Rakudo:

When the typename happens to be a role, autovivifying it involves
attempting to create a punned class of the same name as the role.
Whether this succeeds or not depends on whether the role is
sufficiently complete to serve as a class on its own.

What you’re doing there is actually creating a new class on the fly which has the role composed into it (and contains nothing else), and then making a new object of that class immediately. I don’t think it’s the kind of thing you can then seamlessly merge into an instance of another class which composes the same role.

Which I suspect is why the .perl comes out wrong, although it should probably manage to be smarter than that.

But I think the correct pattern here might be having a Duration object which then becomes a member of the thing which has a duration. I did once come across a genuine use for roles, but I was coding in C++ so I had to use multiple inheritance instead. I know people are using them with Moose, but personally I have no idea of the patterns involved.