<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Toby Inkster</title>
    <description>The latest articles on DEV Community by Toby Inkster (@tobyink).</description>
    <link>https://dev.to/tobyink</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F471552%2Fb0600e6f-48a5-4787-9cbe-9a8832cbaf13.jpeg</url>
      <title>DEV Community: Toby Inkster</title>
      <link>https://dev.to/tobyink</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tobyink"/>
    <language>en</language>
    <item>
      <title>How can we make this Moose faster?</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Sat, 17 Jan 2026 10:05:06 +0000</pubDate>
      <link>https://dev.to/tobyink/how-can-we-make-this-moose-faster-5dl6</link>
      <guid>https://dev.to/tobyink/how-can-we-make-this-moose-faster-5dl6</guid>
      <description>&lt;p&gt;(I make no apologies for the ChatGPT images in my recent blog posts, by the way. No artists are missing out on being paid: I wasn’t going to hire an artist to illustrate these blog posts which will be read by like three people.)&lt;/p&gt;

&lt;p&gt;A while back, I wrote &lt;a href="https://metacpan.org/pod/MooseX::XSAccessor" rel="noopener noreferrer"&gt;MooseX::XSAccessor&lt;/a&gt; which you can add to Moose classes to inspect your attributes and try to replace the accessors with faster XS-based ones. Now I’ve done the same for constructors (&lt;code&gt;new&lt;/code&gt;) and destructors (&lt;code&gt;DESTROY&lt;/code&gt;) with &lt;a href="https://metacpan.org/pod/MooseX::XSConstructor" rel="noopener noreferrer"&gt;MooseX::XSConstructor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are probably still bugs, but initial benchmarks look promising:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              Rate   Standard     XS
Standard    6392/s         --   -43%
XS         11228/s        76%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They’re mostly just a matter of importing the modules and forgetting about them. If the modules detect that your class is too complex for the XS modules to handle, they’ll sit back and let the regular Moose code work its magic. Give them a try. Let me know if they break things. They usually won’t.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>moose</category>
    </item>
    <item>
      <title>Marlin Racing</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Sun, 11 Jan 2026 15:40:29 +0000</pubDate>
      <link>https://dev.to/tobyink/marlin-racing-3b0h</link>
      <guid>https://dev.to/tobyink/marlin-racing-3b0h</guid>
      <description>&lt;p&gt;When &lt;a href="https://toby.ink/blog/2025/12/18/introducing-marlin/" rel="noopener noreferrer"&gt;I first introduced Marlin&lt;/a&gt;, it seemed the only OO framework which could beat its constructor in speed was the one generated by the new Perl core &lt;code&gt;class&lt;/code&gt; keyword. Which seems fair, as that’s implemented in C and is tightly integrated with the Perl interpreter. However, I’m pleased to say that Marlin’s constructors are now faster.&lt;/p&gt;

&lt;p&gt;(Though also I forgot to include Mouse in previous benchmarks, so I’ve rectified that now.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         Rate  Plain   Tiny    Moo  Moose   Core Marlin  Mouse
Plain  1357/s     --    -1%   -48%   -55%   -73%   -77%   -78%
Tiny   1374/s     1%     --   -48%   -54%   -72%   -77%   -78%
Moo    2617/s    93%    91%     --   -13%   -47%   -56%   -58%
Moose  3001/s   121%   118%    15%     --   -39%   -50%   -52%
Core   4943/s   264%   260%    89%    65%     --   -17%   -21%
Marlin 5976/s   340%   335%   128%    99%    21%     --    -4%
Mouse  6237/s   359%   354%   138%   108%    26%     4%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main way I’ve squeezed out a bit of improved performance is by improving how &lt;a href="https://metacpan.org/pod/Class::XSConstructor" rel="noopener noreferrer"&gt;Class::XSConstructor&lt;/a&gt; keeps its metadata.&lt;/p&gt;

&lt;p&gt;Previously, if you called &lt;code&gt;Local::Person-&amp;gt;new()&lt;/code&gt;, the XS constructor would look up the list of supported attributes for the class in &lt;code&gt;@Local::Person::__XSCON_HAS&lt;/code&gt; and loop through that array to initialize each attribute like &lt;code&gt;"name"&lt;/code&gt;, &lt;code&gt;"age"&lt;/code&gt;, etc. If the attribute had a type constraint, it would need to fetch the coderef to validate the value from &lt;code&gt;$Local::Person::__XSCON_ISA{"name"}&lt;/code&gt;, and so on. All these involved looking things up in the class’s stash, which isn’t exactly &lt;em&gt;slow&lt;/em&gt; when done via XS, but could be faster.&lt;/p&gt;

&lt;p&gt;I’ve changed it so that the first time the constructor is called, the XS code pulls together all the data it needs into C structs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;I32&lt;/span&gt;     &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;init_arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;  &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;I32&lt;/span&gt;     &lt;span class="n"&gt;num_aliases&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;SV&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;default_sv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;SV&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;trigger_sv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;CV&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;check_cv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;CV&lt;/span&gt;     &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;coercion_cv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;xscon_param_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;   &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt;    &lt;span class="n"&gt;is_placeholder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;xscon_param_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;I32&lt;/span&gt;     &lt;span class="n"&gt;num_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;CV&lt;/span&gt;    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;build_methods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;I32&lt;/span&gt;     &lt;span class="n"&gt;num_build_methods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt;    &lt;span class="n"&gt;strict_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;  &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;I32&lt;/span&gt;     &lt;span class="n"&gt;num_allow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;xscon_constructor_t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than having to deal with attribute names being Perl SVs, they’re just simple C strings (&lt;code&gt;char*&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;flags&lt;/code&gt; field does a lot of heavy lifting. It is a bit field with booleans indicating whether an attribute is required or optional, whether it should be a weaken reference, and other features. A lot of common defaults (attributes which default to common values like undef, true, false, 0, 1, the empty string, an empty arrayref, or an empty hashref) and common type constraints (Str, Num, Int, ArrayRef, etc) are also encoded into the &lt;code&gt;flags&lt;/code&gt; field, so the constructor can often skip even having to look at &lt;code&gt;default_sv&lt;/code&gt; and &lt;code&gt;check_cv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the same time, the number of features Class::XSConstructor supports has increased, so Marlin now never needs to fall back to generating Pure Perl constructors. (The code for generating Perl constructors has now been deleted!)&lt;/p&gt;

&lt;p&gt;A second trick is one I learned from Mouse in how it implements its strict constructor check. As a reminder, a strict constructor check is like the ones implemented by &lt;a href="https://metacpan.org/pod/MooseX::StrictConstructor" rel="noopener noreferrer"&gt;MooseX::StrictConstructor&lt;/a&gt;, &lt;a href="https://metacpan.org/pod/MooX::StrictConstructor" rel="noopener noreferrer"&gt;MooX::StrictConstructor&lt;/a&gt;, and &lt;a href="https://metacpan.org/pod/MouseX::StrictConstructor" rel="noopener noreferrer"&gt;MouseX::StrictConstructor&lt;/a&gt;, along these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Unpack @_&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%args&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HASH&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Create new object&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nv"&gt;$class&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;# Initialize each attribute&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# Strict constructor check&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;%args&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unrecognized key: &lt;/span&gt;&lt;span class="si"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/^(name|date)$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strict constructors are a really useful feature as a protection against mistyped attributes. But they do come with a speed penalty, which I guess is why Moose and Moo don’t have this feature built in. (Mouse does actually have the feature built in, but requires an extension (MouseX::StrictConstructor) to toggle it on.)&lt;/p&gt;

&lt;p&gt;Mouse’s strict constructor check has virtually zero performance impact. I took a look at the source code to figure out how, and it is pretty smart. It just counts the number of arguments the constructor has used to initialize attributes, and only bothers with the strict constructor check if the total number of arguments is greater than that. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Unpack @_&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%args&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HASH&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Create new object&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nv"&gt;$class&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$used_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Initialize each attribute&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nv"&gt;$used_keys&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nv"&gt;$used_keys&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# Strict constructor check&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;%args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$used_keys&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;%args&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unrecognized key: &lt;/span&gt;&lt;span class="si"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/^(name|date)$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Genius!&lt;/p&gt;

&lt;p&gt;With these changes, Marlin is now significantly faster than the Perl core &lt;code&gt;class&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Mouse still has around 10% faster accessors than Marlin, which I think might be largely down to having an integrated type system allowing pure C function calls for type constraints instead of needing to use &lt;code&gt;call_sv&lt;/code&gt; to call an XS or Perl type check function.&lt;/p&gt;

&lt;p&gt;Marlin does however beat Mouse significantly (around 70% faster) when it comes to delegated methods. Things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.36&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;API_Client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;modifiers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;_log&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;isa&lt;/span&gt;          &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ArrayRef[HashRef]&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;default&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;handles_via&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;handles&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;add_to_log&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;push&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
        &lt;span class="s"&gt;responses&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;ua&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;isa&lt;/span&gt;          &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HTTP::Tiny&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;default&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;HTTP::&lt;/span&gt;&lt;span class="nv"&gt;Tiny&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s"&gt;handles&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;http_get&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
        &lt;span class="s"&gt;http_post&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;around&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http_get&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http_post&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;( $next, $self, @args ) {&lt;/span&gt;
      &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@args&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;add_to_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;API_Client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;http_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;http_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;http_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@responses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Marlin outperforms all other OO frameworks in this kind of method.&lt;/p&gt;

&lt;p&gt;If you want a fast, concise OO framework, consider using Marlin.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>oop</category>
      <category>moose</category>
      <category>moo</category>
    </item>
    <item>
      <title>Introducing Marlin</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Thu, 18 Dec 2025 21:44:05 +0000</pubDate>
      <link>https://dev.to/tobyink/introducing-marlin-4d4n</link>
      <guid>https://dev.to/tobyink/introducing-marlin-4d4n</guid>
      <description>&lt;p&gt;Does the Perl world need another object-oriented programming framework?&lt;/p&gt;

&lt;p&gt;To be honest, probably not.&lt;/p&gt;

&lt;p&gt;But here’s why you might want to give Marlin a try anyway.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Most of your constructors and accessors will be implemented in XS and be really, really fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you accept a few basic principles like “attributes should usually be read-only”, it can be really, really concise to declare a class and its attributes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.20.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;experimental&lt;/span&gt; &lt;span class="sx"&gt;qw(signatures)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Import useful constants, types, etc.&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Marlin::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lexical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lexical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;given_name!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;NonEmptyStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;family_name!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;NonEmptyStr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name_style&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;enum&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sx"&gt;qw/western eastern/&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;western&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;birth_date?&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

    &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;_build_full_name&lt;/span&gt; &lt;span class="p"&gt;( $self ) {&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%s %s&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nb"&gt;uc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;family_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;given_name&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;name_style&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eastern&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%s %s&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;given_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;family_name&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Marlin::&lt;/span&gt;&lt;span class="nv"&gt;Role&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;requires&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bank\_details&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;make_payment&lt;/span&gt; &lt;span class="p"&gt;( $self ) {&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;extends&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Payable&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bank_details!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;HashRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;employee_id!&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;manager?&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Employee&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;given_name&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Simon&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;family_name&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lee&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;name_style&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eastern&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;employee_id&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;bank_details&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$staff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Employee&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;given_name&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lea&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;family_name&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Simons&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;employee_id&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;bank_details&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="s"&gt;manager&lt;/span&gt;       &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$manager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%s's manager is %s.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
    &lt;span class="nv"&gt;$staff&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$staff&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$staff&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;has_manager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some things you might notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It supports most of the features of Moose… or most of the ones you &lt;em&gt;actually use&lt;/em&gt; anyway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Declaring an attribute is often as simple as listing it’s name on the &lt;code&gt;use Marlin&lt;/code&gt; line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can be followed by some options, but if you’re happy with Marlin’s defaults (read-only attributes), it doesn’t need to be.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use the &lt;code&gt;!&lt;/code&gt; to quickly mark an attribute as required instead of the longer &lt;code&gt;{ required =&amp;gt; true }&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use &lt;code&gt;?&lt;/code&gt; to request a predicate method instead of the longer &lt;code&gt;{ predicate =&amp;gt; true }&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benchmarks
&lt;/h2&gt;

&lt;p&gt;My initial benchmarking shows that Marlin is &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         Rate   Tiny  Plain    Moo  Moose Marlin   Core
Tiny   1317/s     --    -2%   -48%   -53%   -54%   -72%
Plain  1340/s     2%     --   -47%   -53%   -53%   -72%
Moo    2527/s    92%    89%     --   -11%   -12%   -47%
Moose  2828/s   115%   111%    12%     --    -2%   -40%
Marlin 2873/s   118%   114%    14%     2%     --   -39%
Core   4727/s   259%   253%    87%    67%    65%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the new Perl core &lt;code&gt;class&lt;/code&gt; keyword generates a constructor faster than Marlin’s. And it is significantly faster; there’s no denying that. However, object construction is only part of what you are likely to need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Rate   Tiny  Moose  Plain   Core    Moo Marlin
Tiny   17345/s     --    -1%    -3%    -7%   -36%   -45%
Moose  17602/s     1%     --    -2%    -6%   -35%   -44%
Plain  17893/s     3%     2%     --    -4%   -34%   -44%
Core   18732/s     8%     6%     5%     --   -31%   -41%
Moo    27226/s    57%    55%    52%    45%     --   -14%
Marlin 31688/s    83%    80%    77%    69%    16%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By accessors, I’m talking about not just standard getter and setters, but also predicate methods and clearers. Marlin and Moo both use Class::XSAccessor when possible, giving them a significant lead over the others. Marlin uses some sneaky tricks to squeeze out a little bit of extra performance by creating aliases for parent class methods directly in the child class symbol tables, allowing Perl to bypass a lot of the normal method resolution stuff.&lt;/p&gt;

&lt;p&gt;I really expected &lt;code&gt;class&lt;/code&gt; to do a lot better than it does. Its readers and writers are basically implemented in pure Perl currently, though I guess there’s scope to improve them in future releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Native Traits / Handles Via / Delegations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         Rate   Tiny   Core  Plain  Moose    Moo Marlin
Tiny    675/s     --   -56%   -57%   -59%   -61%   -61%
Core   1518/s   125%     --    -4%    -8%   -13%   -13%
Plain  1581/s   134%     4%     --    -4%    -9%   -10%
Moose  1642/s   143%     8%     4%     --    -5%    -6%
Moo    1736/s   157%    14%    10%     6%     --    -1%
Marlin 1752/s   160%    15%    11%     7%     1%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don’t know what I mean by native traits, it’s the ability to create small methods like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;add_language&lt;/span&gt; &lt;span class="p"&gt;( $self, $lang ) {&lt;/span&gt;
    &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;languages&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$lang&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As part of the attribute definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
    &lt;span class="s"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;is&lt;/span&gt;           &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;isa&lt;/span&gt;          &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;ArrayRef&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s"&gt;default&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;handles_via&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;handles&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;add_language&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;push&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;count_languages&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s not an awful lot of difference between the performance of most of these, but Marlin &lt;em&gt;slightly&lt;/em&gt; wins. Marlin and Moose are also the only frameworks that include this out of the box without needing extension modules.&lt;/p&gt;

&lt;p&gt;By the way, that &lt;code&gt;default =&amp;gt; []&lt;/code&gt; was not a typo. You can set an empty arrayref or empty hashref as a default, and Marlin will assume you meant something like &lt;code&gt;default =&amp;gt; sub { [] }&lt;/code&gt;, but it cleverly skips over needing to actually call the coderef (slow), instead creating a reference to a new empty array in XS (fast)!&lt;/p&gt;

&lt;h3&gt;
  
  
  Combined
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         Rate   Tiny  Plain   Core  Moose    Moo Marlin
Tiny    545/s     --   -48%   -56%   -58%   -60%   -64%
Plain  1051/s    93%     --   -16%   -19%   -22%   -31%
Core   1249/s   129%    19%     --    -4%    -8%   -18%
Moose  1304/s   139%    24%     4%     --    -4%   -14%
Moo    1355/s   148%    29%     8%     4%     --   -11%
Marlin 1519/s   179%    45%    22%    17%    12%     --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A realistic bit of code that constructs some objects and calls a bunch of accessors and delegations on them. Marlin performs very well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lexical accessors and private attributes
&lt;/h2&gt;

&lt;p&gt;Marlin has first class support for lexical methods!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.42.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
      &lt;span class="s"&gt;name&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s"&gt;internal_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my internal_id&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PRIVATE&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%d: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;internal_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# dies because internal_id is lexically scoped&lt;/span&gt;
  &lt;span class="nv"&gt;Widget&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;internal_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Support for the &lt;code&gt;-&amp;gt;&amp;amp;&lt;/code&gt; operator was added in Perl 5.42. On older Perls (from Perl 5.12 onwards), lexical methods are still supported but you need to use function call syntax (&lt;code&gt;internal_id($w)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;storage =&amp;gt; "PRIVATE"&lt;/code&gt; hint tells Marlin to use inside-out storage for that attribute, meaning that trying to access the internal_id by poking into the object’s internals (&lt;code&gt;$obj-&amp;gt;{internal_id}&lt;/code&gt;) won’t work.&lt;/p&gt;

&lt;p&gt;This gives you true private attributes.&lt;/p&gt;

&lt;p&gt;On Perl 5.18 and above, you can of course declare lexical methods using the normal &lt;code&gt;my sub foo&lt;/code&gt; syntax, so you have private attributes as well as private methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constant attributes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Marlin&lt;/span&gt;
      &lt;span class="s"&gt;name&lt;/span&gt;         &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s"&gt;species_name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;constant&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Homo sapiens&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constant attributes are declared like regular attributes, but are always very read-only and illegal to pass to the constructor.&lt;/p&gt;

&lt;p&gt;Like other attributes, they support delegations, provided the delegated method isn’t one which could change the value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perl version support
&lt;/h2&gt;

&lt;p&gt;Although some of the lexical features need newer versions of Perl, Marlin runs on Perl versions as old as 5.8.8.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future directions
&lt;/h2&gt;

&lt;p&gt;Some ideas I’ve had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If Moose is loaded, create meta object protocol stuff for Marlin classes and roles, like Moo does.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>oop</category>
    </item>
    <item>
      <title>Type::Tiny 2.8.0 Released</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Mon, 31 Mar 2025 16:26:15 +0000</pubDate>
      <link>https://dev.to/tobyink/typetiny-280-released-4l5e</link>
      <guid>https://dev.to/tobyink/typetiny-280-released-4l5e</guid>
      <description>&lt;p&gt;What’s new?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;BoolLike&lt;/strong&gt; type constraint accepts &lt;a href="https://metacpan.org/pod/boolean.pm" rel="noopener noreferrer"&gt;boolean.pm&lt;/a&gt; booleans.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/pod/Type%3A%3AParams" rel="noopener noreferrer"&gt;Type::Params&lt;/a&gt; offers some improvements for DWIM named parameter processing.&lt;/li&gt;
&lt;li&gt;More shortcuts are provided for exporting parameterized versions of type constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Improvements to Type::Params
&lt;/h2&gt;

&lt;p&gt;If your function or method takes named arguments, the &lt;code&gt;list_to_named&lt;/code&gt; option allows these arguments to optionally be provided positionally as a shortcut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  package My::Company;

  use v5.36;
  use Moo;
  use builtin qw( true false );
  use Types::Common qw( PositiveOrZeroNum InstanceOf );
  use Type::Params qw( signature_for );

  ...;

  signature_for pay_money =&amp;gt; (
    method =&amp;gt; true,
    named =&amp;gt; [
      amount =&amp;gt; PositiveOrZeroNum,
      employee =&amp;gt; InstanceOf['Local::Person'],
    ],
    list_to_named =&amp;gt; true,
  );

  sub pay_money ( $self, $arg ) {
    $self-&amp;gt;payroll_account-&amp;gt;withdraw( $arg-&amp;gt;amount );
    $arg-&amp;gt;employee-&amp;gt;bank_account-&amp;gt;deposit( $arg-&amp;gt;amount );
    return $self;
  }

  ...;

  my $co = My::Company-&amp;gt;new( ... );

  # Standard usage is named arguments:
  $co-&amp;gt;pay_money( amount =&amp;gt; 3000, employee =&amp;gt; $alice );
  $co-&amp;gt;pay_money( { amount =&amp;gt; 3000, employee =&amp;gt; $bob } );

  # Or provide them as positional arguments in the same order
  # they were declared in (amount then employee):
  $co-&amp;gt;pay_money( 3000, $carol );

  # Or if the types are unambiguous, switch it up and provide
  # them in the wrong order instead. Still works!
  $co-&amp;gt;pay_money( $dave, 3000 );

  # Or mix and match:
  $co-&amp;gt;pay_money( $eve, amount =&amp;gt; 3000 );
  $co-&amp;gt;pay_money( $eve, { amount =&amp;gt; 3000 } );
  $co-&amp;gt;pay_money( 3000, employee =&amp;gt; $eve );
  $co-&amp;gt;pay_money( 3000, { employee =&amp;gt; $eve } );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exporting Parameterized Types
&lt;/h2&gt;

&lt;p&gt;For certain parameterizable types, there are now shortcuts to export parameterized versions of them.&lt;/p&gt;

&lt;p&gt;For example, supposing you need to deal with numeric arrayrefs quite a lot. That is, arrayrefs containing only numbers. Previously, you’d probably do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  use Types::Common qw( Num ArrayRef );

  ...;

  has favourite_numbers =&amp;gt; ( is =&amp;gt; 'ro', isa =&amp;gt; ArrayRef[Num] );

  ...;

  if ( ArrayRef-&amp;gt;of( Num )-&amp;gt;check( \@my_array ) ) {
    ...;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can easily create a &lt;strong&gt;Nums&lt;/strong&gt; type constraint and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  use Types::Common qw( Num );
  use Types::Standard::ArrayRef Nums =&amp;gt; { of =&amp;gt; Num };

  ...;

  has favourite_numbers =&amp;gt; ( is =&amp;gt; 'ro', isa =&amp;gt; Nums );

  ...;

  if ( is_Nums \@my_array ) {
    ...;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not all parameterizable types support this, but many of the common ones do.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>typetiny</category>
    </item>
    <item>
      <title>Matching simply</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Fri, 14 Jul 2023 20:42:30 +0000</pubDate>
      <link>https://dev.to/tobyink/matching-simply-2c8k</link>
      <guid>https://dev.to/tobyink/matching-simply-2c8k</guid>
      <description>&lt;p&gt;A little over ten years ago, when Perl 5.18 was approaching its release date, I released &lt;a href="https://metacpan.org/pod/match%3A%3Asimple" rel="noopener noreferrer"&gt;match::simple&lt;/a&gt;. This was mostly in response to the smartmatch operator (&lt;code&gt;~~&lt;/code&gt;) being deprecated, but also a solution to the incredibly arcane rules for how the smartmatch operator operated.&lt;/p&gt;

&lt;p&gt;match::simple was intended to be... simpler. The operator looks a little funky because it uses some clever trickery to fake being an infix operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;match::&lt;/span&gt;&lt;span class="nv"&gt;simple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;$that&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For those who don't like the infix syntax, a regular function is also provided:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;match::&lt;/span&gt;&lt;span class="nv"&gt;simple&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;match&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;match&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$that&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its behaviour was always determined by the operand on the right-hand side. Given:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is undef, &lt;code&gt;$a&lt;/code&gt; only matches if it's also undef.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is any other non-reference value, acts like the string equality (&lt;code&gt;eq&lt;/code&gt;) operator.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is a regexp, acts like the regexp binding (&lt;code&gt;=~&lt;/code&gt;) operator.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is a coderef, &lt;code&gt;$a&lt;/code&gt; matches if &lt;code&gt;$b-&amp;gt;($a)&lt;/code&gt; returns true.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is an object, &lt;code&gt;$a&lt;/code&gt; matches if &lt;code&gt;$b-&amp;gt;MATCH($a)&lt;/code&gt; returns true or &lt;code&gt;$a ~~ $b&lt;/code&gt; using &lt;code&gt;~~&lt;/code&gt; operator overloading.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is an arrayref, &lt;code&gt;$a&lt;/code&gt; matches if &lt;code&gt;$a |M| $_&lt;/code&gt; for any element of &lt;code&gt;@{$b}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;$b&lt;/code&gt; is anything else, the operator croaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These seemed simple, sane, and predictable. Yes, some form of numeric matching would have been nice, but I ruled that out because of the ambiguity of numeric strings.&lt;/p&gt;

&lt;p&gt;Plus because if you really need numeric matching, I knew you could wrap the number in a coderef:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://metacpan.org/pod/Type%3A%3ATiny" rel="noopener noreferrer"&gt;Type::Tiny&lt;/a&gt; has always been compatible with &lt;a href="https://metacpan.org/pod/match%3A%3Asimple" rel="noopener noreferrer"&gt;match::simple&lt;/a&gt;. You can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;match::&lt;/span&gt;&lt;span class="nv"&gt;simple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;ArrayRef&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;HashRef&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anyway, fast forward to now, and Perl 5.38 has now been released, which finally removes the long-deprecated smartmatch operator. Thankfully one of the new features it also provides allows for true user-defined infix operators!&lt;/p&gt;

&lt;p&gt;Introducing &lt;a href="https://metacpan.org/pod/Syntax%3A%3AOperator%3A%3AMatches" rel="noopener noreferrer"&gt;Syntax::Operator::Matches&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Syntax::Operator::&lt;/span&gt;&lt;span class="nv"&gt;Matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt; &lt;span class="nv"&gt;matches&lt;/span&gt; &lt;span class="nv"&gt;$that&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses exactly the same logic as match::simple — logic that has been frozen since 2013, but finally has beautiful syntax.&lt;/p&gt;

&lt;p&gt;You can do nice things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Syntax::Operator::&lt;/span&gt;&lt;span class="nv"&gt;Matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="nv"&gt;matches&lt;/span&gt; &lt;span class="nv"&gt;ArrayRef&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="nv"&gt;matches&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Undef&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some of it is just a wrapper around match::simple, but other parts happen purely in XS, so operate much faster.&lt;/p&gt;

&lt;p&gt;If you're looking for something to replace smartmatch in your code, consider &lt;a href="https://metacpan.org/pod/Syntax%3A%3AOperator%3A%3AMatches" rel="noopener noreferrer"&gt;Syntax::Operator::Matches&lt;/a&gt;. If you need backwards compatibility, &lt;a href="https://metacpan.org/pod/match%3A%3Asimple" rel="noopener noreferrer"&gt;match::simple&lt;/a&gt; is still here and isn't going to disappear.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>smartmatch</category>
    </item>
    <item>
      <title>Increasing Perl’s Visibility, Redux</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Wed, 05 Apr 2023 15:19:28 +0000</pubDate>
      <link>https://dev.to/tobyink/increasing-perls-visibility-redux-17g6</link>
      <guid>https://dev.to/tobyink/increasing-perls-visibility-redux-17g6</guid>
      <description>&lt;p&gt;Quite a while ago, &lt;a href="https://toby.ink/blog/2020/02/07/increasing-perls-visibility/" rel="noopener noreferrer"&gt;I blogged about how Perl projects should have websites&lt;/a&gt; to increase not only their visibility, but the visibility of Perl as a whole.&lt;/p&gt;

&lt;p&gt;Perl has had the CPAN and awesome websites like MetaCPAN and its predecessor search.cpan.org for a long time, so unlike how things happen in other programming language ecosystems, many Perl projects have felt no need to start their own websites for documentation, package downloads, and community — all these things were already provided.&lt;/p&gt;

&lt;p&gt;However, I do feel that this centralization keeps Perl content on the Internet very isolated and makes Perl less visible than other programming languages.&lt;/p&gt;

&lt;p&gt;I’ve recently released &lt;a href="https://metacpan.org/dist/Web-PerlDistSite" rel="noopener noreferrer"&gt;Web::PerlDistSite&lt;/a&gt; to provide an easy way to generate a modern-looking website for your project based mainly on its existing pod. You can then publish your site on github.io or your own hosting.&lt;/p&gt;

&lt;p&gt;I used it to create &lt;a href="https://exportertiny.github.io/" rel="noopener noreferrer"&gt;this website for Exporter-Tiny&lt;/a&gt; and also to revamp the existing &lt;a href="https://typetiny.toby.ink/" rel="noopener noreferrer"&gt;website for Type-Tiny&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve got a CPAN distribution and want to create a website for it, Web::PerlDistSite could be a quick way to get started. The documentation is pretty limited right now, but you can &lt;a href="https://github.com/tobyink/p5-web-perldistsite/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; if you need help.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>html</category>
      <category>http</category>
    </item>
    <item>
      <title>Experiments in Overloading</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Sun, 02 Apr 2023 12:03:44 +0000</pubDate>
      <link>https://dev.to/tobyink/experiments-in-overloading-kec</link>
      <guid>https://dev.to/tobyink/experiments-in-overloading-kec</guid>
      <description>&lt;p&gt;Let’s play with overloading a little.&lt;/p&gt;

&lt;p&gt;A simple class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;overload&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0+&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let’s test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test fails.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;We tend to think of &lt;code&gt;0+&lt;/code&gt; as the way to “cast” a Perl variable to a number, so much so that the &lt;a href="https://metacpan.org/pod/overload" rel="noopener noreferrer"&gt;overload&lt;/a&gt; pragma even calls the numeric overload “0+”. However it is of course actually an addition, and we haven’t overloaded the plus operator.&lt;/p&gt;

&lt;p&gt;The simple solution is to just including the &lt;code&gt;fallback =&amp;gt; true&lt;/code&gt; option when overloading. This tells Perl to fill in as many missing overloaded operations it can based on the operations you’ve explicitly provided.&lt;/p&gt;

&lt;p&gt;But I’m not interested in the simple solution. I’m interested in what we can do with the “0+” overload.&lt;/p&gt;

&lt;p&gt;Let’s try rephrasing our test case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This still fails. The equality operator isn’t overloaded either.&lt;/p&gt;

&lt;p&gt;However, this one works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So how is Test2 comparing them?&lt;/p&gt;

&lt;p&gt;The answer is that whenever the right hand side of an &lt;code&gt;is&lt;/code&gt; comparison is a non-reference, Test2 compares them as strings. Specifically, it does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "$left" eq "$right"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for whatever reason, even though we didn’t set &lt;code&gt;fallback =&amp;gt; true&lt;/code&gt;, Perl will happily apply the numeric overload when an object is interpolated into a string and doesn’t have a string overload.&lt;/p&gt;

&lt;p&gt;So let’s add some stringy overloading to our class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Lingua::EN::&lt;/span&gt;&lt;span class="nv"&gt;Numbers&lt;/span&gt; &lt;span class="sx"&gt;qw( num2en )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;overload&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0+&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;num2en&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our previously passing test fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is comparing “forty-two” and “42” as strings.&lt;/p&gt;

&lt;p&gt;So this is where we stumble upon the safe way to cast to a number. And it’s still not &lt;code&gt;0+&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Local::&lt;/span&gt;&lt;span class="nv"&gt;Overloaded&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%d&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%s&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;forty-two&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing the object to &lt;code&gt;sprintf( '%d' )&lt;/code&gt; for integers or &lt;code&gt;sprintf( '%f' )&lt;/code&gt; will actually use the numeric overload without complaining about &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; not being overloaded. This seems the most reliable way to cast an object to a number if it doesn’t have overload fallbacks enabled, or you’re not sure if it does.&lt;/p&gt;

&lt;p&gt;The lesson here is that overloading can be weird in Perl, but using &lt;code&gt;fallback =&amp;gt; true&lt;/code&gt; makes it a lot less weird.&lt;/p&gt;

&lt;p&gt;The other lesson is to use &lt;code&gt;sprintf( '%d' )&lt;/code&gt; or &lt;code&gt;sprintf( '%f' )&lt;/code&gt; to cast to a number instead of &lt;code&gt;0+&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>moo</category>
      <category>overload</category>
    </item>
    <item>
      <title>Introducing Exporter::Almighty</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Sat, 25 Mar 2023 17:02:18 +0000</pubDate>
      <link>https://dev.to/tobyink/introducing-exporteralmighty-mc5</link>
      <guid>https://dev.to/tobyink/introducing-exporteralmighty-mc5</guid>
      <description>&lt;p&gt;Consider a simple module like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;3.14159265358979&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;EULER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2.71828182845905&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;base&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Exporter&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

  &lt;span class="k"&gt;our&lt;/span&gt; &lt;span class="nv"&gt;@EXPORT_OK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qw( PI EULER add )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;our&lt;/span&gt; &lt;span class="nv"&gt;%EXPORT_TAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;arithmetic&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sx"&gt;qw( add )&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sx"&gt;qw( PI EULER )&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;@EXPORT_OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might use it like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="sx"&gt;qw( PI add )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$pi_plus_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://metacpan.org/pod/Exporter%3A%3AAlmighty" rel="noopener noreferrer"&gt;Exporter::Almighty&lt;/a&gt; is a module designed to &lt;em&gt;reduce boilerplate&lt;/em&gt; in your utils-like modules, and &lt;em&gt;increase their functionality&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The initial module can be rewritten as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Exporter::&lt;/span&gt;&lt;span class="nv"&gt;Almighty&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;const&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;3.14159265358979&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;EULER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2.71828182845905&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;arithmetic&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;['&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exporter::Almighty sets up your exporting automatically (but using &lt;a href="https://metacpan.org/pod/Exporter%3A%3ATiny" rel="noopener noreferrer"&gt;Exporter::Tiny&lt;/a&gt; instead of &lt;a href="https://metacpan.org/pod/Exporter" rel="noopener noreferrer"&gt;Exporter&lt;/a&gt;), and calls &lt;code&gt;use strict&lt;/code&gt; and &lt;code&gt;use warnings&lt;/code&gt; on your behalf.&lt;/p&gt;

&lt;p&gt;Exporter::Almighty creates your constants for you, so you don’t need to duplicate your list of constants anywhere.&lt;/p&gt;

&lt;p&gt;A bonus for your caller is that they can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="sx"&gt;qw( $PI $EULER )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To import read-only &lt;code&gt;$PI&lt;/code&gt; and &lt;code&gt;$EULER&lt;/code&gt; variables instead of traditional constants.&lt;/p&gt;

&lt;p&gt;Your caller can also import things lexically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$pi_plus_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lexical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;qw( add $PI )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

 &lt;span class="c1"&gt;# add() and $PI are not defined outside the above block&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your caller can also rename any imported functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;as&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sum_of&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exporter::Almighty has integrations with Type::Tiny making it easy to define and export Type::Tiny type constraints as part of your module. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Exporter::&lt;/span&gt;&lt;span class="nv"&gt;Almighty&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;const&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Types::Standard&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;['&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;']&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;['&lt;/span&gt;&lt;span class="s1"&gt;Calc&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyApp::Calculator&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now people can import the &lt;strong&gt;Int&lt;/strong&gt; and &lt;strong&gt;Num&lt;/strong&gt; type constraints from your module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="sx"&gt;qw( Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They can even import a &lt;code&gt;is_Int&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;MyApp::Util::&lt;/span&gt;&lt;span class="nv"&gt;Maths&lt;/span&gt; &lt;span class="sx"&gt;qw( is_Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ve also defined a &lt;strong&gt;Calc&lt;/strong&gt; class type constraint which can be used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Calc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exporter::Almighty makes defining enum-like data types easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;My::&lt;/span&gt;&lt;span class="nv"&gt;Properties&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Exporter::&lt;/span&gt;&lt;span class="nv"&gt;Almighty&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;enum&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;['&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undead&lt;/span&gt;&lt;span class="p"&gt;']&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Story::&lt;/span&gt;&lt;span class="nv"&gt;Character&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;My::&lt;/span&gt;&lt;span class="nv"&gt;Properties&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;lexical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+Status&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;experimental&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

    &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;STATUS_ALIVE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;meet&lt;/span&gt; &lt;span class="p"&gt;( $self, $other ) {&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;STATUS_ALIVE&lt;/span&gt;
      &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;STATUS_UNDEAD&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Help!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next time you’re writing a module that needs to export things, consider &lt;a href="https://metacpan.org/pod/Exporter%3A%3AAlmighty" rel="noopener noreferrer"&gt;Exporter::Almighty&lt;/a&gt;. It could make things very easy for you, while adding a bunch of useful features for your caller.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>exporteralmighty</category>
      <category>exportertiny</category>
    </item>
    <item>
      <title>Prosody vs Synapse</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Wed, 08 Mar 2023 22:21:05 +0000</pubDate>
      <link>https://dev.to/tobyink/prosody-vs-synapse-10oc</link>
      <guid>https://dev.to/tobyink/prosody-vs-synapse-10oc</guid>
      <description>&lt;p&gt;I recently decided to experiment by setting up a &lt;a href="https://www.matrix.org/" rel="noopener noreferrer"&gt;Matrix&lt;/a&gt; account. And because I always dive head first into things, I of course set up my own Matrix server rather than making an account on a public one. At the same time, I noticed my Jabber/XMPP account had stopped working, so I decided to self-host an XMPP server too.&lt;/p&gt;

&lt;p&gt;For Matrix, I used &lt;a href="https://matrix.org/docs/projects/server/synapse" rel="noopener noreferrer"&gt;Synapse&lt;/a&gt; as that seems the most popular and well-supported implementation. It was mostly just a matter of installing the Ubuntu packages and starting the service, but there was a bit of manual work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default config file is set up to store data in SQLite, but using SQLite is advised against, so I needed to manually create a PostgreSQL database and username, and add those to the config file.&lt;/li&gt;
&lt;li&gt;The default config is missing &lt;code&gt;macaroon_secret_key&lt;/code&gt; and &lt;code&gt;registration_shared_secret&lt;/code&gt; settings, which are kinda important.&lt;/li&gt;
&lt;li&gt;Because I wanted the server to be hosted on a different VPS than my website, I needed to set up delegation and some of the documentation online on how to do that isn’t quite correct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For XMPP, I used &lt;a href="https://prosody.im/" rel="noopener noreferrer"&gt;Prosody&lt;/a&gt; and the install went very smoothly. Again, just install the package and start the service. The only manual work was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Needed to enter a host name in the example config file.&lt;/li&gt;
&lt;li&gt;Ubuntu doesn’t give access to LetsEncrypt certificates to the prosody user, so I needed to fix permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, I would highly recommend Prosody as an XMPP server. Synapse is a good Matrix server too, but the Debian/Ubuntu packagers could take a look at Prosody for an example of a smooth install.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Matrix account is &lt;em&gt;at me colon toby.ink&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My XMPP account is &lt;em&gt;me at toby.ink&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>xmpp</category>
      <category>jabber</category>
      <category>linux</category>
      <category>matrix</category>
    </item>
    <item>
      <title>Using Type::Params Effectively</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Fri, 17 Feb 2023 16:48:37 +0000</pubDate>
      <link>https://dev.to/tobyink/using-typeparams-effectively-d17</link>
      <guid>https://dev.to/tobyink/using-typeparams-effectively-d17</guid>
      <description>&lt;p&gt;One of the modules bundled with &lt;a href="https://metacpan.org/pod/Type%3A%3ATiny" rel="noopener noreferrer"&gt;Type::Tiny&lt;/a&gt; is &lt;a href="https://metacpan.org/pod/Type%3A%3AParams" rel="noopener noreferrer"&gt;Type::Params&lt;/a&gt;, a module&lt;br&gt;
that allows you to validate subroutine signatures using type constraints.&lt;br&gt;
It's one of the more popular parts of the suite.&lt;/p&gt;

&lt;p&gt;This article provides a few hints for using it effectively.&lt;/p&gt;
&lt;h2&gt;
  
  
  When &lt;em&gt;not&lt;/em&gt; to use Type::Params
&lt;/h2&gt;

&lt;p&gt;There are a few places I occasionally see Type::Params being used where&lt;br&gt;
it's really not the best fit.&lt;/p&gt;
&lt;h3&gt;
  
  
  You just want to know if a variable meets a type constraint
&lt;/h3&gt;

&lt;p&gt;Let's say you have a variable &lt;code&gt;$x&lt;/code&gt; and you want to know if it's&lt;br&gt;
an integer. I have seen people do things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Type::&lt;/span&gt;&lt;span class="nv"&gt;Params&lt;/span&gt; &lt;span class="sx"&gt;qw( validate )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;validate&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x is an integer!&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The &lt;code&gt;eval&lt;/code&gt; is used because &lt;code&gt;validate&lt;/code&gt; will throw an exception, when what&lt;br&gt;
we want is a boolean yes/no.)&lt;/p&gt;

&lt;p&gt;This works, yes, but it can be made &lt;em&gt;so much simpler&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Int()&lt;/code&gt; function returns an &lt;strong&gt;Int&lt;/strong&gt; type constraint object which we can&lt;br&gt;
call methods on. In particular, the &lt;code&gt;check&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x is an integer!&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because type libraries also export an &lt;code&gt;is_X()&lt;/code&gt; function for each type&lt;br&gt;
constraint, we can even go one step simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( is_Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;is_Int&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x is an integer!&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not just easier to read; it will also benchmark much, much faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  You want to assert that a variable meets a type constraint
&lt;/h3&gt;

&lt;p&gt;This is a similar situation, except that here we &lt;em&gt;want&lt;/em&gt; an exception to be&lt;br&gt;
thrown.&lt;/p&gt;

&lt;p&gt;I see people do things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Type::&lt;/span&gt;&lt;span class="nv"&gt;Params&lt;/span&gt; &lt;span class="sx"&gt;qw( compile )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$check_int&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;                 &lt;span class="c1"&gt;# assert $x is an integer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we can call methods on the &lt;strong&gt;Int&lt;/strong&gt; type constraint to achieve the&lt;br&gt;
same result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;assert_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can use the &lt;code&gt;assert_X()&lt;/code&gt; functions exported by type constraint&lt;br&gt;
libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Standard&lt;/span&gt; &lt;span class="sx"&gt;qw( assert_Int )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;assert_Int&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, this is not only much clearer, but will perform better in&lt;br&gt;
benchmarks.&lt;/p&gt;
&lt;h2&gt;
  
  
  When to use Type::Params
&lt;/h2&gt;

&lt;p&gt;Type::Params is intended for validating and unpacking an entire list&lt;br&gt;
in one logical step. In particular this is useful for validating the&lt;br&gt;
&lt;code&gt;@_&lt;/code&gt; array of subroutine arguments.&lt;/p&gt;

&lt;p&gt;Consider we have a class something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="sx"&gt;qw( Num )&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $new_y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks safe because the type constraints will ensure that &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;&lt;br&gt;
will always be numeric.&lt;/p&gt;

&lt;p&gt;However, what if somebody does &lt;code&gt;$point-&amp;gt;move_to( 1, '', 'whatever' )&lt;/code&gt;?&lt;br&gt;
Setting &lt;code&gt;y&lt;/code&gt; to the empty string will throw an exception, but &lt;code&gt;x&lt;/code&gt; has&lt;br&gt;
already been changed, so the object is left in an inconsistent state. It&lt;br&gt;
hasn't moved to where we wanted it to move, but it hasn't stayed where&lt;br&gt;
it was either!&lt;/p&gt;

&lt;p&gt;So it's a good idea to validate all the parameters to &lt;code&gt;move_to&lt;/code&gt; up front.&lt;br&gt;
Here's how you could do it using Type::Params:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sigs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;method&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $new_y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;signature&lt;/code&gt; function compiles the function's signature into a coderef&lt;br&gt;
called &lt;code&gt;$check&lt;/code&gt;. This is stored in a &lt;code&gt;state&lt;/code&gt; variable so that it is&lt;br&gt;
compiled only once.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;method&lt;/code&gt; option indicates that this sub will be called as a method,&lt;br&gt;
so will have an invocant (which must be an &lt;strong&gt;Object&lt;/strong&gt;). The &lt;code&gt;positional&lt;/code&gt;&lt;br&gt;
option indicates that this sub expects two numbers followed by a string.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;&amp;amp;$check&lt;/code&gt; with no parentheses takes advantage of the Perl&lt;br&gt;
feature where &lt;code&gt;@_&lt;/code&gt; is automatically passed forward. The &lt;code&gt;$check&lt;/code&gt;&lt;br&gt;
coderef will now validate &lt;code&gt;@_&lt;/code&gt; and return the validated values. If&lt;br&gt;
validation fails, it will throw an exception.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding defaults
&lt;/h2&gt;

&lt;p&gt;Type::Params also supports defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;method&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if the function is called without a &lt;code&gt;$reason&lt;/code&gt;, a default reason&lt;br&gt;
can be supplied. Simple non-reference defaults can be provided as above.&lt;br&gt;
If you need to build a more complex default, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Switching to named parameters
&lt;/h2&gt;

&lt;p&gt;Let's assume we would prefer to call the method like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$point&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;move_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;reason&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatever&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type::Params handles named parameters easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sigs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;named&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sr"&gt;y      =&amp;gt; Num,
            reason =&amp;gt; Str, { default =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $arg-&amp;gt;y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$arg-&amp;gt;reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;$check&lt;/code&gt; coderef will now return just the invocant &lt;code&gt;$self&lt;/code&gt;&lt;br&gt;
and an object &lt;code&gt;$arg&lt;/code&gt; which allows access to the named arguments.&lt;/p&gt;

&lt;p&gt;However, perhaps we want to accept named parameters without rewriting&lt;br&gt;
the guts of &lt;code&gt;move_to&lt;/code&gt; to deal with &lt;code&gt;$arg&lt;/code&gt;. We still want our&lt;br&gt;
&lt;code&gt;$new_x&lt;/code&gt;, &lt;code&gt;$new_y&lt;/code&gt;, and &lt;code&gt;$reason&lt;/code&gt; variables. That is&lt;br&gt;
also possible!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sigs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;method&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;named_to_list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;named&lt;/span&gt;         &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sr"&gt;y      =&amp;gt; Num,
            reason =&amp;gt; Str, { default =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $new_y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;named_to_list&lt;/code&gt; option tells &lt;code&gt;$check&lt;/code&gt; that it needs to &lt;em&gt;accept&lt;/em&gt;&lt;br&gt;
named parameters, but &lt;em&gt;return&lt;/em&gt; them in a positional list.&lt;/p&gt;
&lt;h2&gt;
  
  
  Transitioning
&lt;/h2&gt;

&lt;p&gt;Now we have rewritten &lt;code&gt;move_to&lt;/code&gt; to accept named parameters, but perhaps&lt;br&gt;
there are still places all over our codebase that call &lt;code&gt;move_to&lt;/code&gt; with&lt;br&gt;
positional parameters. How can we accept both?&lt;/p&gt;

&lt;p&gt;Type::Params allows multiple signatures to be combined into one using the&lt;br&gt;
&lt;code&gt;multiple&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;method&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;multiple&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;named_to_list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;named&lt;/span&gt;         &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sr"&gt;y      =&amp;gt; Num,
            reason =&amp;gt; Str, { default =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;$check&lt;/code&gt; will try each signature in order and see which seems to&lt;br&gt;
make sense. &lt;code&gt;move_to&lt;/code&gt; will accept both named and positional arguments.&lt;/p&gt;
&lt;h2&gt;
  
  
  Extra flexibility
&lt;/h2&gt;

&lt;p&gt;For some reason, we now also want to allow people to call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@coordinates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$point&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;move_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@coordinates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And still preserve the two existing ways to call the function.&lt;br&gt;
Type::Params can still handle this situation. Firstly, we add&lt;br&gt;
another option to the &lt;code&gt;multiple&lt;/code&gt; list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;method&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;multiple&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;named_to_list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;named&lt;/span&gt;         &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sr"&gt;y      =&amp;gt; Num,
            reason =&amp;gt; Str, { default =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nv"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="s"&gt;goto_next&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An issue with this new calling style is that instead of returning&lt;br&gt;
four arguments (the invocant, two numbers, and the reason), it returns&lt;br&gt;
three arguments (the invocant, an arrayref, and the reason). But we can&lt;br&gt;
use &lt;code&gt;goto_next&lt;/code&gt; to unpack the arrayref:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="s"&gt;goto_next&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$pair&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$pair&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now it all works!&lt;/p&gt;

&lt;h2&gt;
  
  
  Perl 5.20 subroutine signatures
&lt;/h2&gt;

&lt;p&gt;Perl 5.20 introduced subroutine signatures as an experimental feature.&lt;br&gt;
As of Perl 5.36, the feature is no longer experimental.&lt;/p&gt;

&lt;p&gt;At first glance, this doesn't seem to fit well with Type::Params.&lt;br&gt;
Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sigs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;( $self, $new_x, $new_y, $reason ) {&lt;/span&gt;
        &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;method&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$new_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reason&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $new_y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's... not neat. And we've lost the flexibility to support multiple&lt;br&gt;
different calling styles.&lt;/p&gt;

&lt;p&gt;However, Type::Params also provides a &lt;code&gt;signature_for&lt;/code&gt; function which&lt;br&gt;
inverts its usual declaration style, putting the signature check&lt;br&gt;
&lt;em&gt;outside&lt;/em&gt; the sub, and allowing you to use Perl subroutine signatures&lt;br&gt;
for the sub itself.&lt;/p&gt;

&lt;p&gt;Here's how we'd use it with named + positional calling style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;v5&lt;/span&gt;&lt;span class="mf"&gt;.16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Moo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Types::&lt;/span&gt;&lt;span class="nv"&gt;Common&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sigs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="sr"&gt;y =&amp;gt; ( is =&amp;gt; 'rw', isa =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nv"&gt;signature_for&lt;/span&gt; &lt;span class="s"&gt;move_to&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;method&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;multiple&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;named_to_list&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;named&lt;/span&gt;         &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="sr"&gt;y      =&amp;gt; Num,
              reason =&amp;gt; Str, { default =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;positional&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nv"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cos I want to&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move_to&lt;/span&gt; &lt;span class="p"&gt;( $self, $new_x, $new_y, $reason ) {&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$new_x&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;y( $new_y )&lt;/span&gt;&lt;span class="err"&gt;;
        say &lt;/span&gt;&lt;span class="sr"&gt;$reason;
        return $se&lt;/span&gt;&lt;span class="nv"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;signature_for&lt;/code&gt; keyword operates at run-time, wrapping around&lt;br&gt;
the &lt;code&gt;move_to&lt;/code&gt; sub declared below it. The signature check takes care&lt;br&gt;
of ensuring the parameters are always sent as a list, so the Perl&lt;br&gt;
subroutine signature never needs to deal with named arguments.&lt;/p&gt;

&lt;p&gt;Currently &lt;code&gt;goto_next&lt;/code&gt; is not supported by &lt;code&gt;signature_for&lt;/code&gt;, so the&lt;br&gt;
third calling style we had before will not work as expected. However,&lt;br&gt;
support is planned.&lt;/p&gt;

&lt;p&gt;Hopefully this article has given you an idea of what Type::Params&lt;br&gt;
is capable of, how you can get the most out of it, and when it's better&lt;br&gt;
to use something else.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>typetiny</category>
    </item>
    <item>
      <title>Setting up WordPress in 2023</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Tue, 07 Feb 2023 10:57:26 +0000</pubDate>
      <link>https://dev.to/tobyink/setting-up-wordpress-in-2023-204a</link>
      <guid>https://dev.to/tobyink/setting-up-wordpress-in-2023-204a</guid>
      <description>&lt;p&gt;Here is my recipe for quickly spinning up a WordPress site with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plugins and themes managed by PHP Composer, so they can be checked into version control.&lt;/li&gt;
&lt;li&gt;Several of my favourite plugins installed, including &lt;a href="https://fooplugins.com/foogallery-wordpress-gallery-plugin/" rel="noopener noreferrer"&gt;FooGallery&lt;/a&gt; and &lt;a href="https://www.advancedcustomfields.com/" rel="noopener noreferrer"&gt;Advanced Custom Fields&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A minimal theme combining &lt;a href="https://roots.io/sage/" rel="noopener noreferrer"&gt;Roots Sage 10&lt;/a&gt; and &lt;a href="https://getbootstrap.com/docs/5.2/getting-started/introduction/" rel="noopener noreferrer"&gt;Bootstrap 5.2&lt;/a&gt; (at the time of writing this article 5.3 was an alpha release). and making use of the plugins in places.&lt;/li&gt;
&lt;li&gt;Avoiding shiny WYSIWYG things like the WordPress block editor, page builder GUIs, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You have SSH access to a Linux+Apache web host&lt;/li&gt;
&lt;li&gt;You have a blank MySQL/MariaDB database&lt;/li&gt;
&lt;li&gt;PHP and PHP Composer are installed and working on the web host, along with any optional components WordPress and Roots Sage need&lt;/li&gt;
&lt;li&gt;You have a domain name (or subdomain) pointed at the host&lt;/li&gt;
&lt;li&gt;Node JS, npm, and yarn are installed and working on the web host&lt;/li&gt;
&lt;li&gt;git is installed and working on the web host&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  WordPress Setup
&lt;/h2&gt;

&lt;p&gt;Let’s clone a skeleton site from Github. This includes our &lt;code&gt;composer.json&lt;/code&gt; file along with a minimal &lt;code&gt;index.php&lt;/code&gt; and an example &lt;code&gt;wp-config.php&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd $HOME/sites/test.site.example
git clone https://github.com/tobyink/wp-base2023.git .
composer install
cp wp-config.php.example wp-config.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we edit &lt;code&gt;wp-config.php&lt;/code&gt; to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The domain name&lt;/li&gt;
&lt;li&gt;Database connection info&lt;/li&gt;
&lt;li&gt;Fresh salt from &lt;a href="https://api.wordpress.org/secret-key/1.1/salt/" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That should be enough for us to be able to visit &lt;code&gt;https://$domain/wordpress/wp-admin/&lt;/code&gt; in a browser and complete WordPress’s browser-based setup procedure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Theme Setup
&lt;/h2&gt;

&lt;p&gt;My minimal theme is called &lt;em&gt;Thyme&lt;/em&gt;. It’s based on Roots Sage 10 and is pretty flexible in terms of appearance.&lt;/p&gt;

&lt;p&gt;If you plan on using a different theme, you can skip straight to the conclusion.&lt;/p&gt;

&lt;p&gt;To install &lt;em&gt;Thyme&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd $HOME/sites/test.site.example
cd wp-content/plugins/
git clone https://github.com/roots/acorn.git acorn
cd acorn
git checkout 2.x
composer install
cd ../../..
git clone https://github.com/tobyink/wp-thyme-theme.git thyme
cd wp-content/themes/
ln -s ../../thyme/ thyme
cd ../../thyme/
composer install
yarn install
yarn build
chmod -R ugo+rwX public/ resources/styles/common/_wp_theme.scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, that’s a fair few commands, but don’t let them scare you.&lt;/p&gt;

&lt;p&gt;Once it’s installed, go to &lt;strong&gt;Plugins&lt;/strong&gt; in the WordPress backend and make sure the following key plugins are activated (because the theme needs them!):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acorn&lt;/li&gt;
&lt;li&gt;Advanced Custom Fields&lt;/li&gt;
&lt;li&gt;Classic Editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only &lt;em&gt;after&lt;/em&gt; activating these plugins should you activate the theme.&lt;/p&gt;

&lt;p&gt;Some optional features of the theme require these plugins to be activated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breadcrumb NavXT&lt;/li&gt;
&lt;li&gt;FooGallery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After activating the theme, you can use the &lt;strong&gt;Theme Options&lt;/strong&gt; and &lt;strong&gt;Sections&lt;/strong&gt; forms in the backend to customize site appearance. After making any changes, all your CSS and Javascript files are automatically recompiled.&lt;/p&gt;

&lt;p&gt;(There’s currently a bug in &lt;em&gt;Thyme&lt;/em&gt; where recompilation is broken until you’ve gone to &lt;strong&gt;Theme Options&lt;/strong&gt; and &lt;strong&gt;Sections&lt;/strong&gt; and hit “Update” on both. This is because there’s a few nulls hanging around in the default values which breaks SASS syntax causing CSS compilation errors. Visiting both pages and setting some values flushes out the nulls.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is a pretty simple way to set up an easily-manageable no-nonsense WordPress blog.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>composer</category>
      <category>git</category>
      <category>php</category>
    </item>
    <item>
      <title>Perl Testing in 2023</title>
      <dc:creator>Toby Inkster</dc:creator>
      <pubDate>Tue, 24 Jan 2023 17:38:36 +0000</pubDate>
      <link>https://dev.to/tobyink/perl-testing-in-2023-hd7</link>
      <guid>https://dev.to/tobyink/perl-testing-in-2023-hd7</guid>
      <description>&lt;p&gt;With my open source work, I’ve historically taken an approach which relies more on integration testing than unit testing, but with some of my newer projects, I’ve tried adopting principles from $paidwork and applying them to my free software.&lt;/p&gt;

&lt;p&gt;This is a quick run-down of how I’m structuring my test suite in newer projects. It’s likely that many of my existing projects will never adopt this structure, but some may.&lt;/p&gt;

&lt;h2&gt;
  
  
  Out with the old, in with the new
&lt;/h2&gt;

&lt;p&gt;First step is ditching &lt;a href="https://metacpan.org/pod/Test%3A%3AMore" rel="noopener noreferrer"&gt;Test::More&lt;/a&gt;, &lt;a href="https://metacpan.org/pod/Test%3A%3AFatal" rel="noopener noreferrer"&gt;Test::Fatal&lt;/a&gt;, &lt;a href="https://metacpan.org/pod/Test%3A%3AWarnings" rel="noopener noreferrer"&gt;Test::Warnings&lt;/a&gt;, and other pre-Test2 testing libraries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacpan.org/pod/Test2%3A%3AV0" rel="noopener noreferrer"&gt;Test2::V0&lt;/a&gt; provides a good base to work with, so we add that to our project’s requirements list straight away.&lt;/p&gt;

&lt;p&gt;We’ll round that out with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/pod/Test2%3A%3ARequire%3A%3AAuthorTesting" rel="noopener noreferrer"&gt;Test2::Require::AuthorTesting&lt;/a&gt; to skip certain tests when run on the end user’s machine, and require the &lt;code&gt;AUTHOR_TESTING&lt;/code&gt; environment variable to run. This is useful for tests which are very slow or require a highly specific environment to run in.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/pod/Test2%3A%3ARequire%3A%3AModule" rel="noopener noreferrer"&gt;Test2::Require::Module&lt;/a&gt; to skip certain tests when optional modules are unavailable.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/pod/Test2%3A%3ATools%3A%3ASpec" rel="noopener noreferrer"&gt;Test2::Tools::Spec&lt;/a&gt; to better structure our unit tests.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/pod/Test2%3A%3APlugin%3A%3ABailOnFail" rel="noopener noreferrer"&gt;Test2::Plugin::BailOnFail&lt;/a&gt; for when your tests simply cannot carry on. Use sparingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other Test2 modules that can be nice to have, but that’s a good starter set. The ones I list above are distributed alongside &lt;a href="https://metacpan.org/pod/Test2%3A%3AV0" rel="noopener noreferrer"&gt;Test2::V0&lt;/a&gt;, so you get them “for free”. It is worth explicitly listing them in your project’s dependencies though, in case they are split into separate distributions in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test directory structure
&lt;/h2&gt;

&lt;p&gt;Perl distributions typically keep their tests in a directory called &lt;em&gt;t&lt;/em&gt; found inside the project root. We won’t change that. We will however create two subdirectories within it, &lt;em&gt;t/unit&lt;/em&gt; and &lt;em&gt;t/integration&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You may have other categories of tests which need their own subdirectories too, but these two will be sufficient for most projects.&lt;/p&gt;

&lt;p&gt;If support modules are needed for testing, they can live in &lt;em&gt;t/lib&lt;/em&gt;. If any data files are needed, put them in &lt;em&gt;t/share&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Any especially important tests can included in the &lt;em&gt;t&lt;/em&gt; directory itself for maximum visibility. I recommend giving them numerically-prefixed filenames for better control over the order they run in.&lt;/p&gt;

&lt;p&gt;I will typically include two such tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;t/00start.t&lt;/em&gt; which performs no real testing, but prints relevant information about the system it’s being run on, such as the version numbers of dependencies, the values of important environment variables, etc.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;t/01basic.t&lt;/em&gt; which loads all of your modules, or at least the important ones, then passes without any real testing being done. The purpose of this is to quickly check for syntax errors so extreme that they prevent your code from even compiling. This is a good place for &lt;a href="https://metacpan.org/pod/Test2%3A%3APlugin%3A%3ABailOnFail" rel="noopener noreferrer"&gt;Test2::Plugin::BailOnFail&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;For each module &lt;em&gt;lib/Foo/Bar.pm&lt;/em&gt; there should be a corresponding unit test script &lt;em&gt;t/unit/Foo/Bar.t&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The prelude of this file will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo::Bar&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::Tools::&lt;/span&gt;&lt;span class="nv"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Data::&lt;/span&gt;&lt;span class="nv"&gt;Dumper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The footer will look exactly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;done_testing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in between will be tests for each unit of code. A “unit” would typically be a function, a method, or an important package variable. Tests for a unit should avoid exercising much code outside their unit, and should &lt;em&gt;especially&lt;/em&gt; avoid exercising code outside the target module.&lt;/p&gt;

&lt;p&gt;A fairly extensive unit test for a method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;describe&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method `foo_bar`&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;both defined&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;both defined, but foo is empty string&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;both defined, but bar is empty string&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;both defined, but both are empty string&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo is undefined&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar is undefined&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;both are undefined&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;it works&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$got_foo_bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$got_exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$got_warnings&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nv"&gt;$got_exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;dies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$got_warnings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;warns&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$CLASS&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nv"&gt;$got_foo_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;foo_bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$got_exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no exception thrown&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$got_warnings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no warnings generated&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$got_foo_bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$expected_foo_bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expected string returned&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;call&lt;/span&gt; &lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nv"&gt;call&lt;/span&gt; &lt;span class="s"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$bar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method call didn't alter the values of the attributes&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nv"&gt;diag&lt;/span&gt; &lt;span class="nv"&gt;Dumper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The module itself as a whole can also be considered a “unit” so that very basic module-wide concerns can be tested there.&lt;/p&gt;

&lt;p&gt;A fairly simple module-wide unit test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;describe&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;class `&lt;/span&gt;&lt;span class="si"&gt;$CLASS&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;it inherits from Moo::Object&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;isa_ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$CLASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Moo::Object&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;it can be instantiated&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;can_ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$CLASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integration tests
&lt;/h2&gt;

&lt;p&gt;Integration tests can take a far more freeform approach. These tests should ensure that the system as a whole, or subsystems within it (which may involve multiple modules), work when used together.&lt;/p&gt;

&lt;p&gt;A good place to start is to look at the &lt;em&gt;SYNOPSIS&lt;/em&gt; sections of your documentation and test that they work as advertised.&lt;/p&gt;

&lt;p&gt;Integration tests should use &lt;a href="https://metacpan.org/pod/Test2%3A%3AV0" rel="noopener noreferrer"&gt;Test2::V0&lt;/a&gt; but will often be small enough not to benefit much from &lt;a href="https://metacpan.org/pod/Test2%3A%3ATools%3A%3ASpec" rel="noopener noreferrer"&gt;Test2::Tools::Spec&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running tests locally
&lt;/h2&gt;

&lt;p&gt;The Test2 tool for running your test suite is &lt;a href="https://metacpan.org/pod/App%3A%3AYath" rel="noopener noreferrer"&gt;yath&lt;/a&gt;, but old stalwart &lt;a href="https://metacpan.org/pod/App%3A%3AProve" rel="noopener noreferrer"&gt;prove&lt;/a&gt; also works well. In your project roor directory, you should be able to run &lt;code&gt;yath test&lt;/code&gt; at the command-line to run your entire test suite. &lt;code&gt;prove -lr&lt;/code&gt; should also work.&lt;/p&gt;

&lt;p&gt;If you need more verbose output to see exactly which tests are passing, then append &lt;code&gt;-v&lt;/code&gt; to each command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous integration with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;I will normally use GitHub Actions to automatically run my test suite on each push, on every major version of Perl I support. One of the test runs will load &lt;a href="https://metacpan.org/pod/Devel%3A%3ACover" rel="noopener noreferrer"&gt;Devel::Cover&lt;/a&gt; and use it to upload test coverage data to &lt;a href="https://codecov.io" rel="noopener noreferrer"&gt;Codecov&lt;/a&gt; and &lt;a href="https://coveralls.io" rel="noopener noreferrer"&gt;Coveralls&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This gives me (almost) instant feedback on whether recent commits have broken things or reduced test coverage.&lt;/p&gt;

&lt;p&gt;100% coverage on Coveralls is totally achieveable. 100% coverage on Codecov often takes a lot more work as it measures branch coverage instead of statement coverage. It’s certainly a good goal though.&lt;/p&gt;

&lt;p&gt;Exactly how to set up continuous integration will depend a lot on your built tools, so I won’t go into specifics here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I feel this setup provides a pretty good basis for test-driven Perl development in 2023.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>tdd</category>
      <category>test2suite</category>
    </item>
  </channel>
</rss>
