It’s rare that I find a language that I truly feel innovates upon established conventions and features. Perl6 came out in late 2015 to little fanfare – it was written off by the Perl community as unnecessary change and by the larger programming community as, well, still Perl. I feel that Perl6 fills the same niche that Lisp does: there are a hundred short and elegant ways to do the same thing, and it’s up to the programmer to decide which one works best for them. It’s extensible and customizable so therefore it’ll last a long time.

In the spirit of Perl, Perl6 is extremely terse and can be fairly hard to read. There’s a lot that goes on behind the scenes that you would hardly catch if you weren’t acquainted with the language. To get up to speed, I found the Learn X in Y minutes page for Perl6 extremely helpful. Before continuing, you should skim through that page.

I’ve only been writing Perl6 for a couple of days, so please excuse any errors & message me using the links at the bottom or the discord at the top so I could correct them.

The Whatever Star

(yes, that’s its real name.)

The whatever star inhereits its namesake from the wildcard character, which gets replaced by “whatever” when evaluated by your shell. In Perl6, the whatever star creates an implicit block which can be used in place of anything that expects a Callable. This process is called whatever-currying. Here are the docs: https://docs.perl6.org/type/WhateverCode.

This is useful for a wide variety of reasons. Here’s an example I feel is relatively succinct:

1,1,*+* ...^ * >= 100

I won’t delve too deeply into breaking this down, but this is a list representing every fibonacci number less than 100. ...^ is the sequence operator which takes a list on its left side ending with a generator function and an ending condition on the right side. Once the number generated by the generator function smart matches against the ending condition, the list is complete. You can also pass a whatever star in the right side of ...^ to create an infinite lazy list. To do something like this in another language, you’d have to pass a bogus parameter or call a function dedicated to constructing a list of this type. But, the whatever star allows the programer to explicitly write out cases of this form where arguments are unneeded or special functionality is required.

Implicit Chaining

There is a special variable in Perl6 named $_. It has type (Any) and essentially takes on whatever value that would make sense in the moment. In for loops it becomes the looping parameter, and in blocks of code it becomes the implicit parameter. It can be set explicitly using given constructs (but more on that later). A special feature of Perl6’s syntax is that the . operator implicity calls functions on $_ if a left operand isn’t passed into it. Along with implicit return statements, this encourages a rather elegant form of method chaining – akin to Ruby’s tap or pointfree style Haskell.

Here’s a contrived example: given a list of lists, filter the lists down to only their even elements and print the new lists.

> (1..2 X 1..2).map: { .grep(* %% 2).say }
()
(2)
(2)
(2 2)

The significant code here is { .grep(* %% 2).say }. This is a block that takes an implicit argument (passed in as $_), filters out eveything that isn’t divisible by 2 (.grep(* %% 2)), and prints it to standard output. We can use this block as a standalone callable to see this in action:

> { .grep(* %% 2).say }(1..10)
(2 4 6 8 10)

In my opinion, this idea of implicit chaining opens the opportunity to write elegant, process oriented code.

Redefinable Operators

“The clearest functions are niladic [take no arguments], the second clearest functions are monadic [take one argument], and the third clearest functions are dyadic [take two arguments].”

I don’t remember who this quote is attributed to, but I believe I heard it while hanging around APL folks. It rings true – functions with tons of arguments become less and less clear the more arguments you have. It’s sort of like the unix philosophy: do one thing and do it well. Massive monolithic functions (or objects, or classes…) are a significant code smell.

Perl6 encourages the programmer to dispose of massive functions like this by providing an extremely flexible way to define operators. The operators page in the Perl6 docs is extraordinarily long but very worth it to scroll through.

Most languages that provide the ability to define custom operators have a notion of precedence (sometimes called fixity or strength). Haskell, for example, allows you to define operators as infixl (left associative infix) or infixr (right associative infix) along with a number 0 through 9 describing how tightly they bind to their arguments. What’s unique about Perl6 though is the fine grained control that it offers the programmer over the associativity rules of the operator. In addition to left associative and right associative, Perl6 allows you to specify whether an operator is non-associative, list associative, or chain associative. The specific rules for these are listed in the docs so I won’t bother rehashing it here, but like I said before, it’s very much so worth reading if you’re unfamiliar.

Here’s a real world example of where this has come in handy for me. Perl6 has no predefined operator to string lines of text together, so I defined one myself:

sub infix:<~~~>($a, $b) { $a ~ "\n" ~ $b };

Then, I used it to write a multiline string without having to fudge with things like heredocs or the like:

say 'trepl version 0. https://github.com/aearnus/'
~~~ "running the language { $*PERL.gist } on { $*PERL.compiler.gist }"
~~~ 'type `;help` for help, or type `;quit` or `;exit` to leave.'
~~~ '';

WHO, WHAT, WHERE, WHICH, WHY, and HOW

I love how Perl6 names things. It’s cute and silly enough to be memorable, and descriptive enough to never leave me confused.

WHO, WHAT, WHERE, WHICH, WHY, and HOW are methods that are defined on every object by default. They facilitate much of the reflection and dynamicism that is possible in Perl6. They’re all part of the MOP, Perl6’s meta object protocol.

WHO returns the package that the object was defined in.

WHAT returns the type of the object.

WHERE returns the address of the object.

WHICH returns a unique identifer to the object.

WHY returns documentation about the object.

HOW is important: it returns the metaclass object, which the developers have slyly named the Higher Order Workings object. It provides an interface to all the runtime dynamicism that Perl6 allows.

There is special syntax to call a method on an object’s HOW object, and that syntax is .^.

Here are a few fun things that you can do with a HOW object. Using my $x = "Hello, world!", we can introspect it to find its name,

> $x.^name
Str

what methods you can call on it,

> $x.^methods
(BUILD Capture Int Num chomp starts-with ends-with substr-eq contains indices index rindex pred succ comb match subst-mutate subst lines parse-base samecase samemark samespace word-by-word trim-leading trim-trailing trim words WORDS_AUTODEREF encode NFC NFD NFKC NFKD unival univals wordcase trans parse-names uniparse indent codes chars uc lc tc fc tclc flip ord WHY WHICH Bool Str Stringy DUMP ACCEPTS chop Numeric gist perl ords split substr substr-rw BUILDALL)

its method resolution order (what classes are traversed to call a method on this object?),

> $x.^mro
((Str) (Cool) (Any) (Mu))

and much more. You can even introspect a HOW object:

> $x.HOW.^methods
(archetypes new new_type add_fallback compose roles role_typecheck_list is_composed setup_junction_fallback find_method_fallback has_fallbacks set_name set_shortname name shortname WHY set_why ver auth api set_ver set_auth set_api add_stash add_attribute compose_attributes set_rw rw get_attribute_for_usage attributes add_method methods method_table submethod_table declares_method lookup cache cache_get cache_add add_private_method private_method_table find_private_method set_autogen_proto add_multi_method multi_methods_to_incorporate incorporate_multi_candidates add_meta_method meta_method_table compose_meta_methods add_role roles_to_compose exclude_parent add_parent parents hides hidden set_hidden set_default_parent_type has_default_parent_type get_default_parent_type compute_mro c3_merge mro mro_unhidden find_method find_method_qualified can publish_method_cache isa does type_check publish_type_cache add_trustee trusts is_trusted create_BUILDPLAN BUILDPLAN BUILDALLPLAN set_is_mixin is_mixin set_mixin_attribute mixin_attribute flush_cache setup_mixin_cache mixin generate_mixin mixin_base is_array_type array_type set_array_type get_boolification_mode set_boolification_mode publish_boolification_spec compose_repr repr_composed set_default_invoke_handler set_invocation_attr set_invocation_handler has_invocation_attr invocation_attr_class ...)

By encapsulating all these metamethods into one object, Perl6 makes an obvious delineation between methods that you should use and methods that you can use. Having the power to do whatver you want is a good thing – but should be used with caution. Other languages (looking at you, Ruby) don’t make this distinction, and thus often expose these unsafe functions as first order methods of every single object.

Traits (particularly, is rw)

Every language should have traits, a strong type system, subset types, etc, etc. It makes programming easier and it means you can offload much of the required mental energy onto the compiler. Perl6’s gradual typing is a perfect example of this – but I have so many things to say about the type system that it would be enough to fill 10 blog posts in their entirety. Instead, I’ll focus on one specific example where the type system comes in handy: the is rw trait.

Consider this snippet of Ruby code. This isn’t some contrived example, I’ve actually run into this problem in real life before. It sneaks up in unsuspecting ways.

class UhOh
	attr_accessor :value

	def floor
		@value = @value.floor
	end
end

def nasty_function(x)
	return x.floor
end

my_num = 0.5
my_uhoh = UhOh.new
my_uhoh.value = 0.5

nasty_function(my_num) # After this, my_num still equals 0.5
nasty_function(my_uhoh) # After this, my_uhoh.value now equals 0!

Despite the fact that we called the exact same function on what seemed to be the exact same kind of object, duck typing betrayed us and obfuscated away a mutation that would come back to bite us later.

It comes down to how Ruby handles copy semantics: with a bare type argument like Num, passing it into a function copies the argument into the scope of the function. With a more complicated type such as a user defined class or a list, passing it into a function copies a reference of the argument into the scope of the function. Ruby handles this implicitly, trying to do the right thing without much programmer intervention. Unfortunately, this level of implicit-ness often leads to hard-to-spot bugs. I may love Ruby, but this is a glaring and fatal flaw with the language.

Perl6 takes a note from the Book of Rust and implements a trait which allows the programmer to annotate whether a type implements copy semantics or move semantics. By default, all types in Perl6 implement some form of immutable move semantics – passing a class like UhOh into a function will not work, as neither value nor UhOh are rw, and thus this bug is negated entirely. To achieve the reference passing behavior exhibited above, one must explicitly implement the is rw trait, saying that every instance of that class is readable and writable.

Nothing will explain this better than a code example, so without further ado:

class Okay {
	has $.value is required;
}

class UhOh is rw is Okay { }

sub nasty_function($klass) {
	$klass.value = 0;
}

my $okay = Okay.new: value => 10;
my $uhoh = UhOh.new: value => 10;

nasty_function($okay); # This doesn't work!
# Cannot modify an immutable Int (10)
#  in sub nasty_function at test.p6 line 8
#  in block <unit> at test.p6 line 14
nasty_function($uhoh); # After this, $uhoh.value now equals 0.

Smartmatch

This is a feature that is so inherently Perl that I cannot imagine it ever being implemented in another language. Smartmatch is the embodiment of “this does what you expect it to do”.

It is an operator, ~~, that calls .ACCEPTS on the right hand argument and aliases $_ to its left hand argument. Every object implements .ACCEPTS in some way, shape, or form; and its sole purpose is to do exactly what it should do.

Sound vague? It is. Smartmatch is used in two important ways in Perl6: to power the given... when construct, and to match type signatures.

Given… When

This is Perl6’s form of a case statement, but calling it a case statement wouldn’t do it justice. Here’s an example of how it can be used:

given $str {
	when /hello/ { say 'user typed in "hello"' }
	when /world/ { say 'user typed in "world"' }
}

This block runs the first block if $str ~~ /hello/ returns True, and the second block if $str ~~ /world/ returns True. In this very specific case, this is akin to a switch/case block but matching on regexes instead. We’re not limited to just regexes though, we can mix and match with whatever type smartmatch accepts:

given $str {
	when 10 { say 'user typed in the number 10' }
	when /hello/ { say 'user typed in "hello"' }
	when /world/ { say 'user typed in "world"' }
}

In this case, we first match against $str ~~ 10 to see if the new first block will run. Smartmatching a string against a number is defined as returning True only if the string coerces into the number, so that block only runs if $str is '10'.

As you could imagine, this is a very powerful and extendable operator. There are plenty more things going on here that I haven’t even touched on: smartmatching against booleans, against callables, etc.

Type Signatures

In Perl6, type signatures are treated the same as any other object. A function’s type signature can be inspected using .signature, and you can do runtime type signature matching using the smartmatch operator ~~ on a Capture object.

Check out this example:

sub f(Int $x --> Int) {
	$x + 1
}

say &f.signature;                    # => (Int $x --> Int)
say \(10.WHAT) ~~ &f.signature;      # => True
say \('hello'.WHAT) ~~ &f.signature; # => False

Read more about smartmatching here or here.

P6CRE and the Grammar Engine

I haven’t quite had an opportunity to play around with this yet, but Perl6 revamped the way that it handles regexes. In the spirit of cute names, I’ll refer to it as P6CRE (pronounced picture?): the Perl6 Compatible Regex Engine. They’ve revamped how regexes traditionally work, allowing for spaces between identifiers, full unicode class support, extra quantifiers, readability improvments, so on and so forth.

Along with P6CRE, an entire grammar system reminiscent of PEG grammars is provided to you for free. This system is extremely powerful… powerful enough that Perl6’s parser is actually implemented using the Perl6 grammar engine. I can’t say much more about it considering I haven’t gotten to use it, but I’m eager to take on a project where I can put it to good use.

In Conclusion…

If you haven’t gotten a chance to check out Perl6, here’s your opportunity. If you want to read more code examples, check out the examples tab on the website or visit their page at RosettaCode.

Thanks to the Perl6 discord server at https://discord.gg/gg2a3T6 and #perl6 at freenode for helping me through some confusing moments. Special thanks to the Perl6 developers and timotimo from #perl6 for being extra patient with me while I was frustrated :)

Have any favorite Perl6 features that I missed out on? Want to leave a comment? Message me using the contact info below.


UPDATE: as per AlexDaniel’s suggestion on #perl6, changed !(* % 2) to * %% 2

Comments

Rory O’Kane writes (formatting slightly modified):

Ruby and avoiding accidental mutation

I think you characterize Ruby wrong in your Traits section. The reason my_uhoh.value changes and my_num doesn’t has nothing to do with copy semantics. Ruby passes both my_num and my_uhoh by reference – it doesn’t implicitly copy only the number as you claim. The reason my_uhoh.value changes is that the UhOh#floor method explicitly mutates @value = @value.floor.

I think your confusion is due to an assumption that Float#floor mutates the number it is called on. You think that my_num was only left unchanged because a copy was provided to nasty_function. In fact, #floor does not mutate the number. A demonstration in irb:

my_num = 0.5
my_num
 # => 0.5
my_num.floor
 # => 0
my_num
 # => 0.5

If floor mutated the number, I would expect it to be called floor! according to Ruby convention. That is why your example feels to contrived to me, despite your assurance that it is not. If I had written the UhOh class, I would have named the method floor!, and the bug never would have happened.

Apart from naming the method differently, if you wanted to achieve the same effect in Ruby as the Perl 6 rw trait that you demonstrate, you could call the #freeze method on the object after constructing it:

class Mutable
	attr_accessor :value
	def change
		@value += 1
	end
end

mut = Mutable.new
 # => #<Mutable:0x00007fc5ae26cc78>
mut.value = 3
 # => 3
mut.change
 # => 4
mut.value
 # => 4

mut.freeze
 # => #<Mutable:0x00007fc5ae26cc78 @value=4>
mut.change
 # Traceback (most recent call last):
 # …
 # FrozenError (can't modify frozen Mutable)
mut.value
 # => 4

I called mut.freeze manually above, but you can even override .new so that #freeze is called automatically on every new instance of your object.

Anyway, that is a corrected description of how Ruby can help you prevent unintended mutation. It’s good that Perl 6 has a solution for that problem too.

Ruby and Smartmatch

This is a feature that is so inherently Perl that I cannot imagine it ever being implemented in another language.

In fact, Ruby has a very similar feature too – probably inspired by Perl, as many of Ruby’s features are. Ruby’s casewhen construct calls a custom operator === on each “when” expression to compare it to the “case” value. This sounds the same as your description of Perl 6 calling .ACCEPTS on the “when” expression to compare it to the “given” value.

Ruby’s #=== method (because operators are just method calls in Ruby) is defined for various types as doing some sort of matching – for example, equality for strings, inclusion for ranges, and matching for regexes. And it can be used for type matching as well. Thanks to the Module#=== implementation, MyClass === some_obj will return true only if some_obj is an instance of MyClass or one of its descendants. Ruby doesn’t have an object representation of function signatures, though, so you can’t check whether an object would be accepted as a parameter to a method as you demonstrated you can in Perl 6.

[snipped all but the quote – my response to the comment about #===]

For example, #=== is supposed to be symmetric and associative, which could limit the operator’s flexibility. ~~ doesn’t have those same best practice constraints.

Despite its use of the equals sign, #=== in Ruby is actually not supposed to be symmetric or associative. For example, /oo/ === ‘cool’ evaluates to true (via the Regex#=== method), while 'cool' === /oo/ evaluates to false (via the String#=== method).

As far as I can tell, Ruby’s === really is equivalent in meaning to Perl 6’s ACCEPTS/~~. The only functional difference I can see is that Perl 6 defines custom ACCEPTS implementations for a few more classes than Ruby does. For example, Ruby doesn’t override Array#=== or Enumerable#===, treating them the same as #==, while Perl 6’s ACCEPTS implementation for List has custom handling of “Whatever” elements and lazy Iterables.