Day 22 – A catalogue of operator types

Perl 6 has a very healthy relationship to operators. "An operator is just a funnily-named subroutine", goes the slogan in the community.

In practice, it means you can do this:

sub postfix:<!>($N) {
    [*] 2..$N;
say 6!;    # 720

Yeah, that’s the prototypical factorial example. I promise I won’t do it any more in this post. I swear the only reason we don’t have factorial as a standard operator in the language, is so that we can impress people by defining it.

Anyway, so a postfix operator ! is really just a "funnily-named" subroutine postfix:<!>. Similarly, we have prefix and infix operators, like prefix:<-> and infix:<*>. They’re all just subroutines. I wrote about that before, so I’m not going to hammer on that point.

Operators have different precedence (like infix:<*> binds tighter than infix:<+>)…

$x + $y * $z   # compiler sees $x + ($y * $z)
$x * $y + $z   # compiler sees ($x * $y) + $z

…and different associativity (like infix:</> associates to the left but infix:<=> associates to the right).

$x / $y / $z   # compiler sees ($x / $y) / $z
$x = $y = $z   # compiler sees $x = ($y = $z)

But I wrote about that before too, at quite some length, so I’m not going to revisit that topic.

No, today I just want to talk about the operator categories in general. I think Perl 6 does a nice job of describing the operator types themselves. I don’t see that in many other languages.

Here are all the different types:

 type            position           syntax
======          ==========         ========

prefix          before a term        !X
infix           between two terms    X ! Y
postfix         after a term         X!

circumfix       around               [X]
postcircumfix   after & around       X[Y]

A lot of other languages give you the ability to define your own operators. Many of them provide approaches which are hackish afterthoughts, and only allow you to override existing operators. Some other languages do approach the problem head-on, but end up simplifying the language to decrease the complexity of defining new operators.

Perl 6 approaches, and solves, the problem, head-on. You get all of the above operators, you can refine or override old ones, and you can talk within the language about things like precedence and associativity.

All that is rather nice. But, as usual, Perl 6 goes one step further and starts classifying metaoperators, too.

What’s a metaoperator? That’s our name for when you can extend an operator in a certain way. For example, many languages allow some kind of not-equal operator like infix:<!=>. Perl 6 has another one for string non-equality: infix:<ne>. And then maybe you want to do smart non-matching: infix:<!~~>. And so on — pretty soon you catch on to the pattern: you may, at one point or another, want to invert the result of any boolean matcher. So that’s what Perl 6 provides.

Here are a few examples:

normal op     negated op
=========     ==========
eq            !eq     ( synonym of ne )
~~            !~~
<             !<      ( synonym of >= )
before        !before

Because this particular metaoperator attaches itself before an infix operator, it gets the name infix_prefix_meta_operator:<!>. I was going to say "and yes, you can add your own user-defined metaoperators too", but currently no implementation supports that. Maybe sometime in the future.

There are many other categories of metaoperators. For example the "multiplication reducer" [*] that we used in the factorial example at the top (which takes a list of numbers and multiplies them all together) is really an infix:<*> surrounded by the metaop prefix_circumfix_meta_operator:sym<[ ]>. (It’s "prefix" because it goes before the list of numbers.)

Luckily, we don’t have meta-meta-ops. Already thinking about the metaops is quite a challenge sometimes. But what I like about Perl 6 and the approach it takes to grammar and operators is this: someone did think about it, long and hard. The resulting system has a pleasing simplicity to it.

Perl 6 is very well-suited for building parsers for languages. As one of its neatest tricks, it takes this expressive power and directs it towards the task of defining itself. As a Perl 6 user, you’re given not just an excellent toolbox, but a well-organized workshop to adapt and extend to fit your needs.

5 thoughts on “Day 22 – A catalogue of operator types

  1. “Luckily, we don’t have meta-meta-ops. […]”

    Can meta-ops be defined for other meta-ops?
    If so, meta-meta-ops are already there! :)

    1. I don’t see any theoretical reason meta-meta-ops couldn’t exist. But for all intents and purposes in Perl 6, they don’t. There’s no definition of a metametaop, there’s nothing that parses metametaops, and there’s no specification that mentions it.

      Maybe ultimately the reason is the same no-one talks about “higher-order higher-order programming” (HOHOP): once you have functions that manipulate other functions, that’s sufficient for doing everything. You gain nothing by adding another layer of meta, as the same result can be just as easily achieved by composing more functions on the same layer instead. Similarly, meta-operators compose effortlessly — that is, the operator that results from combining a regular operator with a meta-operator can easily be combined with yet another meta-operator. ![==] would be an example.

  2. “only reason we don’t have factorial as a standard operator in the language, is so that we can impress people by defining it.”

    Your attitude sucks, the factorial function is worth putting in your product, but you left it out so that you can “impress people”. I am not impressed, I would be more impressed if you made a functional language which can be used by experts and novices alike.

    1. Hellooooooo, random angry person on the Internet! Thanks for reading my article, and for letting me know about the quality of my attitude!

      Did you know your Internet comment is eleven times as long as just defining the factorial operator in your program?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s