<?xml version="1.0" encoding="us-ascii"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Perl Advent Calendar 2022</title><id>http://perladvent.org/2022/</id><link href="http://perladvent.org/2022/atom.xml" rel="self"/><updated>2026-04-14T18:25:14Z</updated><author><name>Mark Fowler</name></author><generator uri="https://metacpan.org/pod/XML::Atom::SimpleFeed" version="0.905">XML::Atom::SimpleFeed</generator><entry><title>Fractal Christmas Tree</title><link href="http://perladvent.org/2022/2022-12-27.html"/><id>http://perladvent.org/2022/2022-12-27.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;!-- exit HTML &lt;body&gt; section, go back into &lt;head&gt; section, 
     modify CSS to increase visibility of POD C&lt;&gt; formatting codes
     (which generate HTML &lt;code&gt; tags not inside &lt;table&gt; tags),
     exit &lt;head&gt; section, go back into &lt;body&gt; section,
     CSS changes will apply to the entire HTML document --&gt;
&lt;/body&gt;
&lt;head&gt;
&lt;style&gt;

/* POD text inside C&lt;&gt; tags; generates HTML &lt;code&gt; tags outside &lt;table&gt; tags  */
code {
    background-color: lightblue;
    padding: 2px;
}

/* HTML table cells via &lt;td class=&#39;code&#39;&gt; tags */
/*
.code {
    background-color: none;
}
*/

/* POD text inside &#39;=begin perl&#39; and &#39;=begin code&#39; sections; generates HTML &lt;code&gt; tags inside &lt;table&gt; tags */
table code {
    background: none;
    padding: 0px;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;p&gt;Merry Christmas and Happy New Year! :-)&lt;/p&gt;

&lt;p&gt;Our holiday-themed programming goal is to implement a fun little Perl application, which will display a Christmas tree using the Sierpinski fractal algorithm.&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_10_pink.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;

&lt;p&gt;Let&#38;#39;s begin by reviewing the code for generating Sierpinski Triangle fractals, stored in a file named &lt;a href=&#34;https://github.com/wbraswell/mathperl/blob/1300d49616055f2fd55bb5385b8341005c238e15/lib/MathPerl/Fractal/Sierpinski.pm&#34;&gt;Sierpinski.pm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are an experienced Perl programmer, you will immediately notice the definition and utilization of data types such as &lt;code&gt;integer&lt;/code&gt; and &lt;code&gt;number&lt;/code&gt;, as well as data structures such as &lt;code&gt;integer::arrayref&lt;/code&gt; and &lt;code&gt;integer::arrayref::arrayref&lt;/code&gt; etc. Data types and data structures, along with other Perl programming strategies such as &lt;code&gt;CRITICS&lt;/code&gt; as well as subroutine &lt;code&gt;$RETURN_TYPE&lt;/code&gt; and &lt;code&gt;@ARG&lt;/code&gt; named input arguments, are included for best practices and compatibility with the &lt;a href=&#34;http://rperl.org&#34;&gt;Perl compiler&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ PREPROCESSOR ]]]&lt;br /&gt;# declare Perl-compatible data types &#38;amp; data structures &lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ HEADER ]]]&lt;br /&gt;#use RPerl;  # replaced by PREPROCESSOR for simplicity&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::Sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.14&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# required for /r return AKA non-destructive regex flag&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.008_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ CRITICS ]]]&lt;br /&gt;# USER DEFAULT 1: allow numeric values &#38;amp; print operator&lt;br /&gt;## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls)&lt;br /&gt;## no critic qw(RequireInterpolationOfMetachars)  # USER DEFAULT 2: allow single-quoted control characters &#38;amp; sigils&lt;br /&gt;## no critic qw(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ OO INHERITANCE ]]]&lt;br /&gt;#use parent qw(MathPerl::Fractal);  # disable unnecessary inheritance for simplicity&lt;br /&gt;#use MathPerl::Fractal;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ INCLUDES ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;English&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$Data::Dumper::Deepcopy&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# display human-readable numeric data, not $VAR1-&#38;gt;[0] references&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ SUBROUTINES ]]]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# recursively generate triangles, grouped by recursion level&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$RETURN_TYPE&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@ARG&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;in sierpinski(), received $recursions_remaining = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;in sierpinski(), received $triangle = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/&#39;//gr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # shortcut variables, easier to read in midpoint calculations below&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # calculate midpoints between two coordinates [x1, y1] and [x2, y2] is [(x1+x2)/2, (y1+y2)/2]&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # construct 3 sub-triangles from orinal points and newly-calculated midpoints&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;   &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # $triangle_groups is zero-indexed like all other Perl arrays,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# so we need to subtract one from $recursions_remaining before using as an index,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# in order to avoid an undefined element at element 0;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# also, we need to decrement $recursions_remaining before making recursive calls;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# for both of these reasons, we can decrement now&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # store all triangles grouped by recursion level&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # recurse once for each sub-triangle&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # return after maximum recursion level is reached (conditional block above not entered),&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# or all recursion calls have returned (conditional block above entered);&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# no return value, all generated data is stored directly in $triangle_groups&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# end of class&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let&#38;#39;s see what happens when we call the &lt;code&gt;sierpinski()&lt;/code&gt; subroutine, passing in only 1 level of recursion for simplicity...&lt;/p&gt;

&lt;p&gt;The recursion directly populates &lt;code&gt;$retval&lt;/code&gt; in reverse order, from highest index to lowest index, eventually ending at index 0 with no further recursion to be done, and all the values are returned back to the original subroutine call. Because of this reverse-index population, the hard-coded initial triangle is stored at the highest (not the lowest) index in &lt;code&gt;$retval&lt;/code&gt;, as you can see in the Perl one-liner (two-liner?) below. The initial triangle&#38;#39;s hard-coded definition is done during declaration for brevity, and the to-be-populated element is left as undef.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ perl -e &#38;#39;use MathPerl::Fractal::Sierpinski; my $retval = [undef, [[512, 100], [212, 600], [812, 600]]];&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;MathPerl::Fractal::Sierpinski::sierpinski($retval-&#38;gt;[1], 1, $retval);&#38;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, &lt;code&gt;sierpinski()&lt;/code&gt; will display the 3 &lt;code&gt;[ x, y ]&lt;/code&gt; cartesian coordinates representing the 3 corners of our initial input triangle, received in the &lt;code&gt;my number::arrayref::arrayref $triangle&lt;/code&gt; argument:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;in sierpinski(), received $recursions_remaining = 1&lt;br /&gt;in sierpinski(), received $triangle = $VAR1 = [ [ 512, 100 ], [ 212, 600 ], [ 812, 600 ] ];&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then the Sierpinski algorithm creates 3 sub-triangles and makes a recursive call to &lt;code&gt;sierpinski()&lt;/code&gt; for each sub-triangle:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;in sierpinski(), received $recursions_remaining = 0&lt;br /&gt;in sierpinski(), received $triangle = $VAR1 = [&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;100&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;362,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;662,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;];&lt;br /&gt;&lt;br /&gt;in sierpinski(), received $recursions_remaining = 0&lt;br /&gt;in sierpinski(), received $triangle = $VAR1 = [&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;362,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;212,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;];&lt;br /&gt;&lt;br /&gt;in sierpinski(), received $recursions_remaining = 0&lt;br /&gt;in sierpinski(), received $triangle = $VAR1 = [&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;662,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;812,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;];&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we were to render these 3 sub-triangles in white, it would look like a monochrome triforce:&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_01_white.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;

&lt;p&gt;After all recursion has completed, we are left with our final &lt;code&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/code&gt; data structure, which contains all generated triangles grouped by recursion level:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;have $my_triangle_groups = &lt;br /&gt;$VAR1 = [&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;100&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;362,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;662,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;362,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;212,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;662,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;350&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;812,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;512,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;100&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;212,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;[&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;812,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;600&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;]&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;];&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ultimately, it is the &lt;code&gt;$my_triangle_groups&lt;/code&gt; data which will be rendered to comprise the main triangular body of the Christmas tree.&lt;/p&gt;

&lt;p&gt;Next let&#38;#39;s review the Perl code for generating the Christmas Tree data and rendering the Simple DirectMedia Layer (&lt;a href=&#34;https://metacpan.org/module/SDL&#34;&gt;SDL&lt;/a&gt;) graphics, stored in a file named &lt;a href=&#34;https://github.com/wbraswell/mathperl/blob/1300d49616055f2fd55bb5385b8341005c238e15/lib/MathPerl/Fractal/ChristmasTree.pm&#34;&gt;ChristmasTree.pm&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ HEADER ]]]&lt;br /&gt;#use RPerl;  # disabled for simplicity; data types declared in Sierpinski.pm &#38;amp; inherited below&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::ChristmasTree&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.14&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# required for /r return AKA non-destructive regex flag&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.008_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ CRITICS ]]]&lt;br /&gt;# USER DEFAULT 1: allow numeric values &#38;amp; print operator&lt;br /&gt;## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls)&lt;br /&gt;## no critic qw(RequireInterpolationOfMetachars)  # USER DEFAULT 2: allow single-quoted control characters &#38;amp; sigils&lt;br /&gt;## no critic qw(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ OO INHERITANCE ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;parent&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(MathPerl::Fractal::Sierpinski)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::Sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ INCLUDES ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;English&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$Data::Dumper::Deepcopy&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# display human-readable numeric data, not $VAR1-&#38;gt;[0] references&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# https://metacpan.org/dist/SDL/view/lib/pods/SDL/Event.pod&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# used for window creation &#38;amp; control&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# used for creating Event object&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Events&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# used for Event queue handling functions&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Time::HiRes&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( gettimeofday usleep )&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# used for time-based animation control&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ SUBROUTINES ]]]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# display an animated Christmas tree!&lt;br /&gt;# define hard-coded constant data; call sierpinski() to recursively generate fractal triangles;&lt;br /&gt;# initialize SDL graphics; render static graphics; render dynamic graphics (animation)&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;generate_fractal__render_animation&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$RETURN_TYPE&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # [ DATA FOR SIZES &#38;amp; SHAPES &#38;amp; COLORS;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;#   HARD-CODED 1024x768 RESOLUTION &#38;amp; 32-BIT COLOR DEPTH ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # initial triangle&#39;s 3 corners as [x, y] Euclidean coordinates&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;212&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;812&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# bottom right&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_red&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;105&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;220&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_orange&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;150&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_green&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;220&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_blue&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_purple&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;175&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_white&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_brown&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;140&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # colors as [r, g, b] triplets; number of colors is number of recursions&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_green&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# green needs to be the color of the smallest, and thus most numerous, triangles&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_blue&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_red&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_white&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # rectangle in format [ x, y, width, height ]&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_rectangle_trunk&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;601&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;050&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;130&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;562&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;130&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# bottom right&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;155&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;562&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# top right&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # colors for animated Christmas tree lights&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_purple&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_orange&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # [ PREPARE &#38;amp; MAKE INITIAL RECURSIVE CALL ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # declare &#38;amp; initialize final array outside of the recursive subroutine for easy direct access by all recursive calls&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # initial triangle is in a triangle group by itself&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # initial call to recursive subroutine&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::Sierpinski::sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # regex to (g)lobally (s)earch for numbers incorrectly wrapped in &#39;single-quotes&#39; by Dumper,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# replace by // empty string, no lvalue $variable so directly (r)eturn modified string;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# https://perldoc.perl.org/perlop#s%2FPATTERN%2FREPLACEMENT%2Fmsixpodualngcer&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have $my_triangle_groups = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/&#39;//gr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # [ INITIALIZE GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # https://metacpan.org/dist/SDL/view/lib/pods/SDL/Events.pod&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@SDL_EVENTS&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;no_such_event&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_ACTIVEEVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_KEYDOWN SDL_KEYUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_MOUSEMOTION SDL_MOUSEBUTTONDOWN SDL_MOUSEBUTTONUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_JOYAXISMOTION SDL_JOYBALLMOTION SDL_JOYHATMOTION SDL_JOYBUTTONDOWN SDL_JOYBUTTONUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_QUIT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_SYSWMEVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_VIDEORESIZE SDL_VIDEOEXPOSE&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_USEREVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_NUMEVENTS&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# constant data&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # SDL includes moved into [[[ INCLUDES ]]] section above&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # initialize SDL video &#38;amp; application &#38;amp; event;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# we do not call $my_SDL_app-&#38;gt;run() anywhere in this program, instead we use the while() run loop below&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;SDL::init&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SDL_INIT_VIDEO&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Merry Christmas!!  Perl Advent 2022!!!&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;width&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;                     &lt;span class=&#34;comment&#34;&gt;# hard-coded 1024x768 resolution&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;768&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;depth&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;                       &lt;span class=&#34;comment&#34;&gt;# hard-coded 32-bit color&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;resizeable&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;                     &lt;span class=&#34;comment&#34;&gt;# allow window resize; does not scale window contents&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # [ RENDER STATIC GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # draw Christmas tree branches &#38;amp; snow tinsel &#38;amp; ornaments &#38;amp; lights;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# iterate through triangle groups in reverse order, due to reverse population during recursion&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # https://metacpan.org/dist/SDL/view/lib/pods/SDLx/Surface.pod&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # refresh window on every triangle for fun cascade drawing effect&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # draw Christmas tree trunk &#38;amp; Star of Bethlehem&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_rect&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_rectangle_trunk&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_brown&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# refresh window&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # [ RENDER DYNAMIC (ANIMATED) GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # set initial index for accessing Christmas tree lights colors&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # set initial time for changing Christmas tree lights colors&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;gettimeofday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    #print &#39;have $seconds_start = &#39;, $seconds_start, &#38;quot;\n&#38;quot;;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # the main run loop, used instead of calling $my_SDL_app-&#38;gt;run();&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# animate forever, until SDL_QUIT event is received in GUI window via &#38;lt;Alt-F4&#38;gt; keypress or window close mouse click,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# or in CLI window via &#38;lt;Ctrl-C&#38;gt; keypress&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # pump the event loop, gathering events from input devices&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;SDL::Events::pump_events&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # poll for currently pending events&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SDL::Events::poll_event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have @SDL_EVENTS[&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;] = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@SDL_EVENTS&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;()]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # we only care about the SDL_QUIT event telling us to exit&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL_QUIT&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;SDL_QUIT event received, exiting&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # get current time, for comparison with start time of current Christmas tree lights color&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;gettimeofday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    #    print &#39;have $seconds_current = &#39;, $seconds_current, &#38;quot;\n&#38;quot;;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # twinkle Christmas tree lights every 1 second&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # reset start time to current time, for time cycle of next animation frame&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # iterate through lights colors&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have $my_color = $my_lights_colors-&#38;gt;[&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;] = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # wrap back to beginning of lights colors when end is reached&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # only update second-smallest triangles, not the green of the Christmas tree itself&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # redraw green of Christmas tree&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # redraw Star of Bethlehem&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;            # refresh window once for every Christmas tree lights color change, for synchronized lights&lt;br /&gt;&lt;/span&gt;            &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # briefly pause between each while() loop iteration, to avoid overloading CPU;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# ( 1_000_000 microseconds per second ) / ( 10_000 microseconds per iteration) = 100 iterations per second;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# need at least 100 while loop iterations per second, in order to process all of the otherwise-ignored&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# SDL_MOUSEMOTION events which are caused by simply moving the mouse over top of the window&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;usleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# end of generate_fractal__render_animation()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# end of class&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above Christmas tree code is pretty much the simplest 2-D graphics rendering system I could write using SDL, with the ability to be exited gracefully instead of having to type &lt;code&gt;Ctrl-Z&lt;/code&gt; and then &lt;code&gt;$ killall -KILL perl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Last, we only need a few lines of driver code to run it all:&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/wbraswell/mathperl/blob/1300d49616055f2fd55bb5385b8341005c238e15/script/sierpinski_triangles_christmas.pl&#34;&gt;sierpinski_triangles_christmas.pl&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Fractal Christmas Tree&lt;br /&gt;# Sierpinski triangles animated using SDL graphics&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ HEADER ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.008_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ INCLUDES ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::ChristmasTree&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ OPERATIONS ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;MathPerl::Fractal::ChristmasTree::generate_fractal__render_animation&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you were to run the above program, which includes 5 colors for 5 levels of recursion, then you would see a rendered series of images similar to the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ ./sierpinski_triangles_christmas.pl&lt;/code&gt;&lt;/pre&gt;

&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_00_blank.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_01_white.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_02_red.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_03_blue.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_04_pink.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_05_green.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_10_pink.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_11_orange.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;
&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_12_purple.png&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;

&lt;p&gt;However, before you can run this program you will need to install the SDL dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ cpanm -v SDL SDLx::App SDL::Event SDL::Events&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, the easiest way to run this Fractal Christmas Tree program is to copy or download the monolithic code below (instead of all 3 files above), and then paste it into a single executable Perl file:&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://github.com/wbraswell/mathperl/blob/1300d49616055f2fd55bb5385b8341005c238e15/script/sierpinski_triangles_christmas_monolith.pl&#34;&gt;sierpinski_triangles_christmas_monolith.pl&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Fractal Christmas Tree, Monolithic Single File&lt;br /&gt;# Sierpinski triangles animated using SDL graphics&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ PREPROCESSOR ]]]&lt;br /&gt;# declare Perl-compatible data types &#38;amp; data structures &lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ HEADER ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.14&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# required for /r return AKA non-destructive regex flag&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.008_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ CRITICS ]]]&lt;br /&gt;# USER DEFAULT 1: allow numeric values &#38;amp; print operator&lt;br /&gt;## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls)&lt;br /&gt;## no critic qw(RequireInterpolationOfMetachars)  # USER DEFAULT 2: allow single-quoted control characters &#38;amp; sigils&lt;br /&gt;## no critic qw(ProhibitConstantPragma ProhibitMagicNumbers)  # USER DEFAULT 3: allow constants&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ INCLUDES ]]]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;English&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$Data::Dumper::Deepcopy&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# display human-readable numeric data, not $VAR1-&#38;gt;[0] references&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# https://metacpan.org/dist/SDL/view/lib/pods/SDL/Event.pod&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# used for window creation &#38;amp; control&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# used for creating Event object&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Events&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# used for Event queue handling functions&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Time::HiRes&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( gettimeofday usleep )&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# used for time-based animation control&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ CONSTANTS ]]]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [ DATA FOR SIZES &#38;amp; SHAPES &#38;amp; COLORS;&lt;br /&gt;#   HARD-CODED 1024x768 RESOLUTION &#38;amp; 32-BIT COLOR DEPTH ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# initial triangle&#39;s 3 corners as [x, y] Euclidean coordinates&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;212&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;812&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# bottom right&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_red&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;105&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;220&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_orange&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;150&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_green&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;220&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_blue&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_purple&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;175&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_white&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_brown&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;140&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# colors as [r, g, b] triplets; number of colors is number of recursions&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_green&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# green needs to be the color of the smallest, and thus most numerous, triangles&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_blue&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_red&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_color_white&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# rectangle in format [ x, y, width, height ]&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_rectangle_trunk&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;601&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;050&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;130&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;562&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;130&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# bottom right&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;155&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# bottom point&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;462&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# top left&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;562&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]];&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# top right&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# colors for animated Christmas tree lights&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_color_pink&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_purple&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_orange&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# https://metacpan.org/dist/SDL/view/lib/pods/SDL/Events.pod&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@SDL_EVENTS&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw(&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;no_such_event&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_ACTIVEEVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_KEYDOWN SDL_KEYUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_MOUSEMOTION SDL_MOUSEBUTTONDOWN SDL_MOUSEBUTTONUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_JOYAXISMOTION SDL_JOYBALLMOTION SDL_JOYHATMOTION SDL_JOYBUTTONDOWN SDL_JOYBUTTONUP&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_QUIT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_SYSWMEVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_VIDEORESIZE SDL_VIDEOEXPOSE&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_USEREVENT&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;SDL_NUMEVENTS&lt;br /&gt;)&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# constant data&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ OPERATIONS ]]]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [ PREPARE &#38;amp; MAKE INITIAL RECURSIVE CALL ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# declare &#38;amp; initialize final array outside of the recursive subroutine for easy direct access by all recursive calls&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# initial triangle is in a triangle group by itself&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# initial call to recursive subroutine&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_initial&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# regex to (g)lobally (s)earch for numbers incorrectly wrapped in &#39;single-quotes&#39; by Dumper,&lt;br /&gt;# replace by // empty string, no lvalue $variable so directly (r)eturn modified string;&lt;br /&gt;# https://perldoc.perl.org/perlop#s%2FPATTERN%2FREPLACEMENT%2Fmsixpodualngcer&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have $my_triangle_groups = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/&#39;//gr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [ INITIALIZE GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# SDL includes moved into [[[ INCLUDES ]]] section above&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# initialize SDL video &#38;amp; application &#38;amp; event;&lt;br /&gt;# we do not call $my_SDL_app-&#38;gt;run() anywhere in this program, instead we use the while() run loop below&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SDL::init&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SDL_INIT_VIDEO&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDLx::App&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Merry Christmas!!  Perl Advent 2022!!!&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;width&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;                     &lt;span class=&#34;comment&#34;&gt;# hard-coded 1024x768 resolution&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;768&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;depth&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;                       &lt;span class=&#34;comment&#34;&gt;# hard-coded 32-bit color&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;resizeable&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;                     &lt;span class=&#34;comment&#34;&gt;# allow window resize; does not scale window contents&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL::Event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [ RENDER STATIC GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# draw Christmas tree branches &#38;amp; snow tinsel &#38;amp; ornaments &#38;amp; lights;&lt;br /&gt;# iterate through triangle groups in reverse order, due to reverse population during recursion&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$i&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # https://metacpan.org/dist/SDL/view/lib/pods/SDLx/Surface.pod&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # refresh window on every triangle for fun cascade drawing effect&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# draw Christmas tree trunk &#38;amp; Star of Bethlehem&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_rect&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_rectangle_trunk&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_brown&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# refresh window&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [ RENDER DYNAMIC (ANIMATED) GRAPHICS ]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# set initial index for accessing Christmas tree lights colors&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# set initial time for changing Christmas tree lights colors&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;gettimeofday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;#print &#39;have $seconds_start = &#39;, $seconds_start, &#38;quot;\n&#38;quot;;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# the main run loop, used instead of calling $my_SDL_app-&#38;gt;run();&lt;br /&gt;# animate forever, until SDL_QUIT event is received in GUI window via &#38;lt;Alt-F4&#38;gt; keypress or window close mouse click,&lt;br /&gt;# or in CLI window via &#38;lt;Ctrl-C&#38;gt; keypress&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # pump the event loop, gathering events from input devices&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;SDL::Events::pump_events&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # poll for currently pending events&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SDL::Events::poll_event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have @SDL_EVENTS[&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;] = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@SDL_EVENTS&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;()]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # we only care about the SDL_QUIT event telling us to exit&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_event&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SDL_QUIT&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;SDL_QUIT event received, exiting&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # get current time, for comparison with start time of current Christmas tree lights color&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;gettimeofday&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;#    print &#39;have $seconds_current = &#39;, $seconds_current, &#38;quot;\n&#38;quot;;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # twinkle Christmas tree lights every 1 second&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # reset start time to current time, for time cycle of next animation frame&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$seconds_start&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$seconds_current&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # iterate through lights colors&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;have $my_color = $my_lights_colors-&#38;gt;[&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;] = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # wrap back to beginning of lights colors when end is reached&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;})&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_lights_colors_index&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # only update second-smallest triangles, not the green of the Christmas tree itself&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # redraw green of Christmas tree&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;lt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_group&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$j&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_colors&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # redraw Star of Bethlehem&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_up&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;draw_trigon_filled&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_triangle_star_down&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$my_color_yellow&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # refresh window once for every Christmas tree lights color change, for synchronized lights&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$my_SDL_app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # briefly pause between each while() loop iteration, to avoid overloading CPU;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# ( 1_000_000 microseconds per second ) / ( 10_000 microseconds per iteration) = 100 iterations per second;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# need at least 100 while loop iterations per second, in order to process all of the otherwise-ignored&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# SDL_MOUSEMOTION events which are caused by simply moving the mouse over top of the window&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;word&#34;&gt;usleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10_000&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# [[[ SUBROUTINES ]]]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# recursively generate triangles, grouped by recursion level&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$RETURN_TYPE&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;integer&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@ARG&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;in sierpinski(), received $recursions_remaining = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;in sierpinski(), received $triangle = &#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;substitute&#34;&gt;s/&#39;//gr&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # shortcut variables, easier to read in midpoint calculations below&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # calculate midpoints between two coordinates [x1, y1] and [x2, y2] is [(x1+x2)/2, (y1+y2)/2]&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;[((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # construct 3 sub-triangles from orinal points and newly-calculated midpoints&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;number::arrayref::arrayref&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_a_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_b_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$point_c&lt;/span&gt;   &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # $triangle_groups is zero-indexed like all other Perl arrays,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# so we need to subtract one from $recursions_remaining before using as an index,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# in order to avoid an undefined element at element 0;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# also, we need to decrement $recursions_remaining before making recursive calls;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# for both of these reasons, we can decrement now&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # store all triangles grouped by recursion level&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # recurse once for each sub-triangle&lt;br /&gt;&lt;/span&gt;        &lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_a&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_b&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sierpinski&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$subtriangle_c&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$recursions_remaining&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$triangle_groups&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # return after maximum recursion level is reached (conditional block above not entered),&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# or all recursion calls have returned (conditional block above entered);&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;# no return value, all generated data is stored directly in $triangle_groups&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;comment&#34;&gt;# end of package &#39;main&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you review the graphics rendering code above, you will see the &lt;code&gt;while(1)&lt;/code&gt; main run loop which twinkles the Christmas tree lights, displaying an animated color change once every second.&lt;/p&gt;

&lt;p&gt;Run it yourself and bask in the Perl yuletide glory of your very own Sierpinski triangle fractal Christmas tree!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ ./sierpinski_triangles_christmas_monolith.pl&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Merry Christmas to all, and to all a good night! :-)&lt;/p&gt;

&lt;br&gt;
&lt;center&gt;&lt;img src=&#34;fractal_christmas_tree_20_animated.gif&#34; alt=&#34;Fractal Christmas Tree&#34; width=&#34;75%&#34;&gt;&lt;/center&gt;

&lt;/div&gt;</summary><updated>2022-12-27T00:00:00Z</updated><category term="Perl"/><author><name>Will &#39;the Chill&#39; Braswell</name></author></entry><entry><title>Create Your Excel using Perl!</title><link href="http://perladvent.org/2022/2022-12-26.html"/><id>http://perladvent.org/2022/2022-12-26.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Create-Your-Excel-using-Perl&#34;&gt;Create Your Excel using Perl!&lt;/h2&gt;

&lt;h3 id=&#34;Intro&#34;&gt;Intro&lt;/h3&gt;

&lt;p&gt;A long-long time ago, during the Advent of 2001, there was an article about manipulating Excel spreadsheets using Perl, &lt;a href=&#34;https://perladvent.org/2001/14th/&#34;&gt;Spreadsheet::WriteExcel&lt;/a&gt;. It&#38;#39;s been a while now, so Santa decided to ask the Wise Old Elf to write another article about creating Excel files using Perl.&lt;/p&gt;

&lt;p&gt;There were only 3 days until Advent, with lots of articles missing, so the Wise Old Elf immediately delegated this task to Wunorse Openslae, and he chose wisely - as always. Wunorse was a master of managing Excel files and started to work on that article immediately.&lt;/p&gt;

&lt;h3 id=&#34;Preface&#34;&gt;Preface&lt;/h3&gt;

&lt;p&gt;Some historical background: The older module &lt;a href=&#34;https://metacpan.org/pod/Spreadsheet::WriteExcel&#34;&gt;Spreadsheet::WriteExcel&lt;/a&gt; is for creating Excel files compatible with Excel 97, 2000, 2002, 2003 and 2007, mainly with &lt;code&gt;.xls&lt;/code&gt; extension. It is mostly compatible with Excel::Writer::XLSX, so &lt;a href=&#34;https://metacpan.org/pod/Spreadsheet::WriteExcel#Migrating-to-Excel::Writer::XLSX&#34;&gt;migrating to the newer version&lt;/a&gt; should be as easy as Christmas pie. However such a migration is more like a heavy Christmas pudding loaded with goodness and lots of issues might arise during the process.&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;Spreadsheet::ParseExcel&lt;/code&gt; for reading the older Excel files having &lt;code&gt;.xls&lt;/code&gt; extension, on the other hand you should use &lt;code&gt;Spreadsheet::ParseXLSX&lt;/code&gt; or &lt;code&gt;Spreadsheet::XLSX&lt;/code&gt; to open and manipulate existing Excel files having the &lt;code&gt;.xlsx&lt;/code&gt; extension. This article deals with creating Excel files in &lt;code&gt;.xlsx&lt;/code&gt; format.&lt;/p&gt;

&lt;h3 id=&#34;Basics&#34;&gt;Basics&lt;/h3&gt;

&lt;p&gt;First things first: import the module, initialize an &lt;code&gt;.xlsx&lt;/code&gt; file, add some worksheets, input some data on them and finally close the file, as you would do with a usual filehandle. This looks a bit different, though:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;use Excel::Writer::XLSX;&lt;br /&gt;&lt;br /&gt;#Create excel file               &lt;br /&gt;my $merry = Excel::Writer::XLSX-&#38;gt;new( &#38;#39;xmas.xlsx&#38;#39; );&lt;br /&gt;#create the workbooks&lt;br /&gt;my $xmas = $merry-&#38;gt;add_worksheet(&#38;#39;Merry&#38;#39;);&lt;br /&gt;my $baking_sheet = $merry-&#38;gt;add_worksheet(&#38;#39;Xmas&#38;#39;);&lt;br /&gt;my $stats = $merry-&#38;gt;add_worksheet(&#38;#39;Everybody!&#38;#39;);&lt;br /&gt;$xmas-&#38;gt;write( &#38;#39;A1&#38;#39;, &#38;#39;Merry Christmas!&#38;#39; );&lt;br /&gt;$merry-&#38;gt;close();&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I skipped to display the usual stuff from the beginning of the script, everyone should know by heart: &lt;code&gt;use strict; use warnings;&lt;/code&gt;, etc. This will be the skeleton or the Christmas themed frame of our script. You can put everything else in between, depending on Santa&#38;#39;s needs, a list of Christmas cookies from around Europe in hash format is a good example, including some stats.&lt;/p&gt;

&lt;h3 id=&#34;Formatting&#34;&gt;Formatting&lt;/h3&gt;

&lt;p&gt;To add some format to your cells, use the &lt;code&gt;add_format()&lt;/code&gt; method. You can either just call it on your &lt;code&gt;$workbook&lt;/code&gt; without parameters or pass a hash of formatting properties to it. The rest depends on your choice from the two options. It is more convenient - in my opinion - to create a format object with a hash, rather than calling the formatting methods afterwards. But the option is there to call the specific format methods for as you need them. I will demonstrate both ways in the examples.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;#This will create a christmas colored landscape with snow in the background represented as dots.&lt;br /&gt;my %props = ( color =&#38;gt; &#38;#39;red&#38;#39;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;size =&#38;gt; &#38;#39;20&#38;#39;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;bg_color =&#38;gt; &#38;#39;green&#38;#39;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pattern =&#38;gt; 18,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;align =&#38;gt; &#38;#39;center&#38;#39;,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;);&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;br /&gt;my $format = $workbook-&#38;gt;add_format( %props );&lt;br /&gt;#write welcome text with formatting to top left cell&lt;br /&gt;$xmas-&#38;gt;write( &#38;#39;A1&#38;#39;, &#38;#39;Merry Christmas!&#38;#39;, $format);&lt;br /&gt;#Set the column width.&lt;br /&gt;$xmas-&#38;gt;set_column(&#38;#39;A:A&#38;#39;, 30);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will need to pass the format object to your write method as a parameter:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$merry-&#38;gt;write( &#38;#39;A1&#38;#39;, &#38;#39;Merry Christmas!&#38;#39;, $format );&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might notice the &lt;code&gt;set_column()&lt;/code&gt; method, this takes the column &#38;#39;coordinates&#38;#39; as a parameter and a number which is the actual width. Let&#38;#39;s add some more format objects for later.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;my $format2 = $merry-&#38;gt;add_format();&lt;br /&gt;&lt;br /&gt;#Setting format using formatting methods, red and bold text, green background, center alignment, green background and dotted borders (for the snowflakes)&lt;br /&gt;&lt;br /&gt;$format2-&#38;gt;set_color( &#38;#39;red&#38;#39; );&lt;br /&gt;$format2-&#38;gt;set_bold();&lt;br /&gt;$format2-&#38;gt;set_size( 12 );&lt;br /&gt;$format2-&#38;gt;set_bg_color( &#38;#39;green&#38;#39; );&lt;br /&gt;$format2-&#38;gt;set_align( &#38;#39;center&#38;#39; );&lt;br /&gt;$format2-&#38;gt;set_border( 4 );&lt;br /&gt;&lt;br /&gt;#Just some snowflakes as border&lt;br /&gt;my $format3 = $merry-&#38;gt;add_format( border =&#38;gt; 4,);&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Writing-data-into-cells&#34;&gt;Writing data into cells&lt;/h3&gt;

&lt;p&gt;There are two ways to do that: you can use either the row-column notation or the A1 notation as described in &lt;a href=&#34;https://metacpan.org/pod/Excel::Writer::XLSX#Cell-notation&#34;&gt;Cell notation&lt;/a&gt;. First of all we need some data so let&#38;#39;s compose our cookies list. We will use a hash of array refs to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;my $cookies = { &lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Hungary =&#38;gt; [ &#38;#39;bejgli&#38;#39;, &#38;#39;h&#38;oacute;labda&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Scandinavia =&#38;gt; [ &#38;#39;Pepparkakor&#38;#39;, &#38;#39;Ruiskakut&#38;#39;, &#38;#39;Lussekatter&#38;#39;, &#38;#39;Krumkake&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Netherlands =&#38;gt; [ &#38;#39;Spekulaas&#38;#39;, &#38;#39;Kerstkranjes&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Germany =&#38;gt; [ &#38;#39;Lebkuchen&#38;#39;, &#38;#39;Stollen&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Switzerland =&#38;gt; [ &#38;#39;Basler L&#38;auml;ckerli&#38;#39;, &#38;#39;Brunsli&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Italy =&#38;gt; [ &#38;#39;Panettone&#38;#39;, &#38;#39;Pignoli&#38;#39;, &#38;#39;Cannoli&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Spain =&#38;gt; [ &#38;#39;Polvorones&#38;#39;, &#38;#39;Mantecados&#38;#39;, &#38;#39;Turr&#38;oacute;n&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Greece =&#38;gt; [ &#38;#39;Melomakarona&#38;#39; ],&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;};&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;br /&gt;#Sort the countries alphabetically&lt;br /&gt;my @countries = sort keys %$cookies;&lt;br /&gt;&lt;br /&gt;#Add the cookies to the baking sheet, one country per column.&lt;br /&gt;$baking_sheet-&#38;gt;set_column( 0, scalar keys %$cookies, 15 );&lt;br /&gt;$baking_sheet-&#38;gt;write( &#38;#39;A1&#38;#39;, \@countries, $format2 );&lt;br /&gt;&lt;br /&gt;my $i = 0;&lt;br /&gt;for ( sort keys %$cookies ) {&lt;br /&gt;&#38;nbsp;&#38;nbsp;#Place Your cookies to the baking sheet&lt;br /&gt;&#38;nbsp;&#38;nbsp;$baking_sheet-&#38;gt;write( 1, $i, [ $cookies-&#38;gt;{$_} ], $format3 );&lt;br /&gt;&#38;nbsp;&#38;nbsp;$i++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#write some statistics about how many types of cookies we have per country&lt;br /&gt;$stats-&#38;gt;write( &#38;#39;A1&#38;#39;, [ \@countries ], $format2 );&lt;br /&gt;&lt;br /&gt;#Reset the counter&lt;br /&gt;$i = 0;&lt;br /&gt;#count how many cookies we have country wise.&lt;br /&gt;for ( sort keys %$cookies ) {&lt;br /&gt;&#38;nbsp;&#38;nbsp;#Place Your cookies to the baking sheet&lt;br /&gt;&#38;nbsp;&#38;nbsp;$stats-&#38;gt;write( $i, 1, scalar @{$cookies-&#38;gt;{$_}} , $format3 );&lt;br /&gt;&#38;nbsp;&#38;nbsp;$i++;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Many things are happening here.&lt;/p&gt;

&lt;p&gt;First we get a list of countries sorted alphabetically. Second we are writing those countries into the first row, alongside some formats, defined above. Then comes the first usage of &lt;code&gt;write()&lt;/code&gt;, where we are using the A1 notation to start from the top left corner, then comes the reference to the &lt;code&gt;@countries&lt;/code&gt; array, followed by the format2. When we pass an array reference to &lt;code&gt;write()&lt;/code&gt;, it will write the elements of the array in the same row. It is equivalent to write_row(). If you pass an array ref of array refs to &lt;code&gt;write()&lt;/code&gt;, it is the same as calling &lt;code&gt;write_col()&lt;/code&gt;, it will write to the columns, as demonstrated in the lines 22 and 27.&lt;/p&gt;

&lt;p&gt;For more on &lt;code&gt;write()&lt;/code&gt;, please check the &lt;a href=&#34;https://metacpan.org/pod/Excel::Writer::XLSX#write(-$row,-$column,-$token,-$format-)&#34;&gt;write section&lt;/a&gt; on the module&#38;#39;s page.&lt;/p&gt;

&lt;h3 id=&#34;Outro&#34;&gt;Outro&lt;/h3&gt;

&lt;p&gt;Santa was cheerful about this guide, especially that it contains the long avaited Christmas cookie statistics. And perhaps the next task will be to extend this report with more Christmas cookies from around the world.&lt;/p&gt;

&lt;p&gt;We just scratched the surface of &lt;code&gt;Excel::Writer::XLSX&lt;/code&gt; with this short tutorial. You can find a comprehensive guide on CPAN, &lt;a href=&#34;https://metacpan.org/pod/Excel::Writer::XLSX&#34;&gt;Excel::Writer::XLSX&lt;/a&gt;. This is a very useful and powerful module, which can deal with a range of tasks from the basics of generating reports to the heavy lifting of the work with VBA in Excel. To cover all of its features would take a whole book.&lt;/p&gt;

&lt;p&gt;You can find the whole script on my Github &lt;a href=&#34;https://github.com/x1mandi/padvent_code/blob/main/cookies_test.pl&#34;&gt;cookies_test.pl&lt;/a&gt;, so that you can test it on your own and play with the module. Merry Christmas!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-26T00:00:00Z</updated><category term="Perl"/><author><name>Csaba Sim&#225;ndi</name></author></entry><entry><title>How to wrap a camel?</title><link href="http://perladvent.org/2022/2022-12-25.html"/><id>http://perladvent.org/2022/2022-12-25.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;How-to-wrap-a-camel&#34;&gt;How to wrap a camel?&lt;/h2&gt;

&lt;p&gt;In the elf workshop, elves never knew what to do when they were passed a camel and were instructed to wrap it to put it on Santa&#38;#39;s sleigh. Many times the elves skipped wrapping and loaded camels right onto the sleigh. This practice garnered the North Pole many letters from children around the world being unable to install and use their new camel! &lt;b&gt;&#38;quot;How do I install Perl?&#38;quot;, &#38;quot;cpanm: command not found&#38;quot;, &#38;quot;Permission denied&#38;quot;, &#38;quot;collect2.exe: error: ld returned 1 exit status&#38;quot;, &#38;quot;Can&#38;#39;t locate&#38;quot;&lt;/b&gt; they cried out for help. Some gift recipients even refused to install their camel despite their needs and desires, as they didn&#38;#39;t want to deal with the difficulties of installing Perl. Claus tasked master elf, Artie, to design a fool-proof way of wrapping a camel for enjoyment by children across the world.&lt;/p&gt;

&lt;p&gt;Artie got right to work as they knew from experience that wrapping a camel was not a trivial task. First, Artie attempted to wrap a camel with &lt;a href=&#34;https://metacpan.org/module/PAR::Packer&#34;&gt;PAR::Packer&lt;/a&gt;, but discovered that the wrapped camel was unusable when the user&#38;#39;s glibc version or operating system differed from the one Artie used to wrap. Artie knew Santa had high standards and would want a more robust solution, so they continued to do research. Artie stumbled upon the &lt;a href=&#34;https://github.com/jart/cosmopolitan&#34;&gt;Cosmopolitan Libc&lt;/a&gt; and &lt;a href=&#34;https://justine.lol/ape.html&#34;&gt;Actually Portable Executables&lt;/a&gt;. What if you built a single binary version of Perl that runs on six operating systems and melded your camel to the binary? Then, everyone can use camels! Artie got to work creating &lt;a href=&#34;https://computoid.com/posts/Perl-is-Actually-Portable.html&#34;&gt;Actually Portable Perl (APPerl)&lt;/a&gt; with the &lt;a href=&#34;https://metacpan.org/module/Perl::Dist::APPerl&#34;&gt;Perl::Dist::APPerl&lt;/a&gt; package for building APPerl and wrapping camels with it.&lt;/p&gt;

&lt;p&gt;Close to Christmas, Artie finally had &lt;a href=&#34;https://metacpan.org/module/Perl::Dist::APPerl&#34;&gt;Perl::Dist::APPerl&lt;/a&gt; ready and notified Santa. Santa requested an immediate demonstration to determine if it is a viable way of wrapping camels starting this Christmas season.&lt;/p&gt;

&lt;h3 id=&#34;Wrapping-Pure-Perl-camels&#34;&gt;Wrapping Pure Perl camels&lt;/h3&gt;

&lt;p&gt;Artie created some directories to contain the camel project.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    mkdir -p wrap_camel/src wrap_camel/script
    cd wrap_camel&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie created an example script and saved it to &lt;code&gt;script/cameltype&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;cancel_christmas&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;$!&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$numhumps&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;How many humps?\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$numhumps&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;readline&#34;&gt;&#38;lt;STDIN&#38;gt;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;cancel_christmas&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;chomp&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$numhumps&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;last&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$numhumps&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=~&lt;/span&gt; &lt;span class=&#34;match&#34;&gt;/^\d+$/&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Your nose ain&#39;t too bright, $numhumps is not a number\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%results&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Dromedary\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Bactrian\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$results&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$numhumps&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Maybe a reindeer? Probably not a camel!\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie noted to Santa that Pure Perl scripts can be wrapped with an existing version of APPerl, off the shelf builds of APPerl can be found on the &lt;a href=&#34;https://computoid.com/APPerl/#RELEASES&#34;&gt;APPerl webpage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Artie picked &lt;code&gt;perl-small.com&lt;/code&gt; off the shelf and created an APPerl project:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    wget -O src/perl.com &#38;#39;https://github.com/G4Vi/Perl-Dist-APPerl/releases/latest/download/perl-small.com&#38;#39;
    chmod +x src/perl.com
    apperlm init --name default_config&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie edited &lt;code&gt;default_config&lt;/code&gt; in the newly created &lt;code&gt;apperl-project.json&lt;/code&gt; to copy in the &lt;code&gt;cameltype&lt;/code&gt; script and set the destination executable name to &lt;code&gt;cameltype.com&lt;/code&gt;, the name is important as &lt;code&gt;argv[0]&lt;/code&gt; is used to determine which script embedded in APPerl to run.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;quot;dest&#38;quot; : &#38;quot;cameltype.com&#38;quot;,
    &#38;quot;zip_extra_files&#38;quot; : { &#38;quot;bin&#38;quot; : [&#38;quot;script/cameltype&#38;quot;] },&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie wrapped the camel and demonstrated the &lt;code&gt;cameltype&lt;/code&gt; binary:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    apperlm build
    ./cameltype.com&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa said, &#38;quot;Ho, ho, ho. Very impressive, Artie! What about the camels with XS modules?&#38;quot;&lt;/p&gt;

&lt;h3 id=&#34;Wrapping-camels-with-XS-modules&#34;&gt;Wrapping camels with XS modules&lt;/h3&gt;

&lt;p&gt;Artie said, &#38;quot;Camels with XS modules can also be wrapped into APPerl. However, every XS-wrapping elf needs a Linux build environment.&#38;quot; Santa, a big fan of developing on several platforms, asked, &#38;quot;Why is that required?&#38;quot; Artie replied, &#38;quot;While APPerl binaries are also ZIP files, APPerl binaries are statically linked, so there is no way to add binary modules after compilation. To wrap with XS modules, the Cosmopolitan Libc and Perl must be built from scratch.&#38;quot; Santa was reasonably worried about this and asked Artie to show him once more.&lt;/p&gt;

&lt;p&gt;Artie ran some commands to create a new APPerl project and install build dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    mkdir -p ../wrap_xs_camel/script
    cd ../wrap_xs_camel
    apperlm install-build-deps
    apperlm init --name default_config --base v5.36.0-small-v0.1.0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie created &lt;code&gt;MerryChristmas.xs&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;#define PERL_NO_GET_CONTEXT&lt;br /&gt;#include &#38;quot;EXTERN.h&#38;quot;&lt;br /&gt;#include &#38;quot;perl.h&#38;quot;&lt;br /&gt;#include &#38;quot;XSUB.h&#38;quot;&lt;br /&gt;#include &#38;lt;stdio.h&#38;gt;&lt;br /&gt;&lt;br /&gt;MODULE = MerryChristmas    PACKAGE = MerryChristmas&lt;br /&gt;&lt;br /&gt;void&lt;br /&gt;merry_christmas()&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;CODE:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;printf(&#38;quot;Merry Christmas from XS!\n&#38;quot;);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie created &lt;code&gt;MerryChristmas.pm&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MerryChristmas&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;our&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;0.0&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;require&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;XSLoader&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;XSLoader::load&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;MerryChristmas&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$VERSION&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie created a &lt;code&gt;script/merrychristmas&lt;/code&gt; to demo the module:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MerryChristmas&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;MerryChristmas::merry_christmas&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie edited &lt;code&gt;default_config&lt;/code&gt; in &lt;code&gt;apperl-project.json&lt;/code&gt; to add the &lt;code&gt;MerryChristmas&lt;/code&gt; module to the Perl repo, copy in the script, and set the destination executable name.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;quot;dest&#38;quot; : &#38;quot;merrychristmas.com&#38;quot;,
    &#38;quot;perl_repo_files&#38;quot; : { &#38;quot;ext/MerryChristmas&#38;quot; : [&#38;quot;MerryChristmas.pm&#38;quot;, &#38;quot;MerryChristmas.xs&#38;quot;]},
    &#38;quot;+MANIFEST&#38;quot; : [&#38;quot;__perlarchlib__/MerryChristmas.pm&#38;quot;, &#38;quot;bin/merrychristmas&#38;quot;],
    &#38;quot;+perl_onlyextensions&#38;quot; : [&#38;quot;MerryChristmas&#38;quot;],
    &#38;quot;zip_extra_files&#38;quot; : { &#38;quot;bin&#38;quot; : [&#38;quot;script/merrychristmas&#38;quot;] }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Artie checked out the config, configured, built, and tested out the Merry Christmas message contraption:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    apperlm checkout default_config
    apperlm configure
    apperlm build
    ./merrychristmas.com&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa said, &#38;quot;Great work, now we can wrap camels of all shapes and sizes to spread cheer to the world! I&#38;#39;d like to put this into practice immediately&#38;quot;. Artie replied, &#38;quot;Thank you Santa, I&#38;#39;ll get to work teaching all the other elves how to wrap a camel.&#38;quot;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-25T00:00:00Z</updated><category term="Perl"/><author><name>Gavin Hayes</name></author></entry><entry><title>Looking at the Christmas Numbers</title><link href="http://perladvent.org/2022/2022-12-24.html"/><id>http://perladvent.org/2022/2022-12-24.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;All the elves know: it is mainly about spreading joy. But some numbers need to be kept in check - maybe with bar charts.&lt;/p&gt;

&lt;h3 id=&#34;Get-some-code&#34;&gt;Get some code&lt;/h3&gt;

&lt;p&gt;Because they is no time for a long coding session during the jolly season, they just grab some example from &lt;a href=&#34;https://metacpan.org/module/Chart::Manual::Types&#34;&gt;Chart::Manual::Types&lt;/a&gt;. Every line of it is explained there in detail. Once the code is pasted, they change the first dataset (animal names =&#38;gt; gift recipients) and paste into the following sets (rows) the real numbers. At last axis and legend need to be labeled properly and a first draft is ready:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Chart::Bars&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Chart::Bars&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw/ Peter Paul Mary/&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;40&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;80&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;80&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;30&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;60&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Christmas Expenses&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;x_label&lt;/span&gt;       &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Recipient&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_label&lt;/span&gt;       &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;legend_labels&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;2020&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;2021&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;2022&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;    &lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_grid_lines&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;true&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;min_val&lt;/span&gt;       &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;precision&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt;  &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_grid_lines&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray70&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;misc&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray55&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;text&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray55&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;x_label&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray40&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_label&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray40&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;        &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray20&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;png&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;bars1.png&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The values under the Hash-key &lt;code&gt;colors&lt;/code&gt; just gray out the less important parts, so that the chart is more pleasant.&lt;/p&gt;

&lt;img src=&#34;https://raw.githubusercontent.com/lichtkind/Chart/main/dev/example/advent/bars1.png&#34;    alt=&#34;first bar chart&#34;  width=&#34;300&#34; height=&#34;300&#34;&gt;

&lt;h3 id=&#34;Finding-Colors&#34;&gt;Finding Colors&lt;/h3&gt;

&lt;p&gt;The only issue now are the dataset colors, which are optimized for contrast (they scream). Intuitive would be to have shades of the same color to signify that neighbouring bars are about the same person, only some numbers are older than others. To achieve that let&#38;#39;s pick some appealing color from the table in the lower half of &lt;a href=&#34;https://metacpan.org/module/Graphics::Toolkit::Color::Constant&#34;&gt;Graphics::Toolkit::Color::Constant&lt;/a&gt;. I like &lt;code&gt;&#38;#39;royalblue3&#38;#39;&lt;/code&gt; of the &lt;i&gt;CSS&lt;/i&gt; standard. It also has the advantage of providing a workable gradient (list of shades) for free. So just add:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset0&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;royalblue4&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset1&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;royalblue3&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset2&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;royalblue2&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only counterintuitive part of this code is to understand that the first &lt;code&gt;add_dataset&lt;/code&gt; only adds X-axis labels and the following &lt;code&gt;add_dataset&lt;/code&gt; is &lt;code&gt;dataset0&lt;/code&gt;.&lt;/p&gt;

&lt;img src=&#34;https://raw.githubusercontent.com/lichtkind/Chart/main/dev/example/advent/bars2.png&#34;    alt=&#34;first bar chart&#34;  width=&#34;300&#34; height=&#34;300&#34;&gt;

&lt;h3 id=&#34;Customize-Colors&#34;&gt;Customize Colors&lt;/h3&gt;

&lt;p&gt;Good, but much of the Christmas business reacts to what was last year. How do we highlight a certain dataset with a more red&#38;#39;ish color, while still keeping saturation and lightness in the targeted scheme of the gradient we had before? For that we load the whole toolkit (a direct dependency of &lt;code&gt;Chart&lt;/code&gt;) and import also the helper function &lt;code&gt;color&lt;/code&gt;, to keep it all short and sweet.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Graphics::Toolkit::Color&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;color&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;royalblue3&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Hue&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;-220&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Please make sure to have atleast the version 1.03 installed to use that feature.&lt;/p&gt;

&lt;img src=&#34;https://raw.githubusercontent.com/lichtkind/Chart/main/dev/example/advent/bars3.png&#34;    alt=&#34;first bar chart&#34;  width=&#34;300&#34; height=&#34;300&#34;&gt;

&lt;h3 id=&#34;Open-the-Color-Factory&#34;&gt;Open the Color Factory&lt;/h3&gt;

&lt;p&gt;Normal people would be good now, but what would a super picky designer, who just came from the &lt;i&gt;New York Fashion Week&lt;/i&gt; say? Maybe something like: how lame - I want a gradient from &lt;i&gt;Glacier Lake&lt;/i&gt; to &lt;i&gt;Harbor Blue&lt;/i&gt;. Alright - let&#38;#39;s check quickly if &lt;a href=&#34;https://metacpan.org/module/Graphics::ColorNames::PantoneReport&#34;&gt;Graphics::ColorNames::PantoneReport&lt;/a&gt; is installed by &lt;code&gt;grep&lt;/code&gt; &#38;#39;ing the result of &lt;code&gt;Graphics::ColorNames::all_schemes&lt;/code&gt; and if so, create our own three color gradient with the colors from this summers &lt;i&gt;Pantone Report&lt;/i&gt;. (Other standards like &lt;i&gt;X&lt;/i&gt;, &lt;i&gt;HTML&lt;/i&gt; or &lt;i&gt;VACCC&lt;/i&gt; are available too - just look at &lt;a href=&#34;https://metacpan.org/module/Bundle::Graphics::ColorNames&#34;&gt;Bundle::Graphics::ColorNames&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@gradient&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;PantoneReport:Glacier Lake&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;gradient_to&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;PantoneReport:Harbor Blue&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset0&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gradient&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset1&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gradient&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;dataset2&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$gradient&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If more datasets are present - just increase the second argument of the method &lt;code&gt;gradient_to&lt;/code&gt;.&lt;/p&gt;

&lt;img src=&#34;https://raw.githubusercontent.com/lichtkind/Chart/main/dev/example/advent/bars4.png&#34;    alt=&#34;first bar chart&#34;  width=&#34;300&#34; height=&#34;300&#34;&gt;

&lt;p&gt;When grouping the values by year instead of recipient, we have to switch X-axis and legend labeling and transpose the data. But also change the colors since they have now to express the difference between people. This does not fit on a linear scale because every human has many different qualities. But the colors still have to go together well to create a harmonious chart. For that task you can create complementary colors, which are maximally different in hue, but same in lightness and saturation (unless the advanced arguments of the method &lt;code&gt;complementary&lt;/code&gt; are used).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@gradient&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;lapisblue&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;complementary&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/Graphics::Toolkit::Color&#34;&gt;Graphics::Toolkit::Color&lt;/a&gt; still holds some more options, but that was enough to get a taste for whats possible.&lt;/p&gt;

&lt;img src=&#34;https://raw.githubusercontent.com/lichtkind/Chart/main/dev/example/advent/bars5.png&#34;    alt=&#34;first bar chart&#34;  width=&#34;300&#34; height=&#34;300&#34;&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;With &lt;a href=&#34;https://metacpan.org/module/Graphics::Toolkit::Color&#34;&gt;Graphics::Toolkit::Color&lt;/a&gt; you can quickly color you chart after your liking. Check all example code and images &lt;a href=&#34;https://github.com/lichtkind/Chart/tree/main/dev/example/advent&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-24T00:00:00Z</updated><category term="Perl"/><author><name>lichtkind</name></author></entry><entry><title>At the Present Factory</title><link href="http://perladvent.org/2022/2022-12-23.html"/><id>http://perladvent.org/2022/2022-12-23.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Father Christmas is very old-school and so is his Perl code. There are no towering software engineering marvels - just a bunch of wonderful scripts: small, meticulously written, very readable and changeable. And because there are so well organized, his system scales up to billions of cheering children.&lt;/p&gt;

&lt;p&gt;Reporting about such a high volume of numbers has to be graphical - charts are needed. They are getting mass produced by scripts that convert one dataset into one chart of a particular layout and design by a call like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;perl script.pl data.tsv &#38;gt; chart.png&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This approach allows maximal flexibility since source and target names are set from the outside and the scripts don&#38;#39;t have to be adapted, even if the data comes from a database or a web scraper. But how to write such a converter script?&lt;/p&gt;

&lt;h3 id=&#34;Establishing-the-Pipe&#34;&gt;Establishing the Pipe&lt;/h3&gt;

&lt;p&gt;Basic examples can be found under &lt;a href=&#34;https://metacpan.org/module/Chart::Manual::Types&#34;&gt;Chart::Manual::Types&lt;/a&gt;. But the code there only uses inline data added by the &lt;code&gt;add_dataset&lt;/code&gt; method. In our case we have to use &lt;code&gt;add_datafile&lt;/code&gt;, which accepts file names or handles and loads an entire table of space or tab separated values (empty rows and perl style comments ignored). Here a short example with only three data rows:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;Peter Paul Mary&lt;br /&gt;30    40   80 &lt;br /&gt;80    60   30 &lt;br /&gt;50    30   60 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can produce such files with &lt;a href=&#34;https://metacpan.org/module/Text::CSV&#34;&gt;Text::CSV&lt;/a&gt; by setting the property &lt;code&gt;sep_char&lt;/code&gt; to &lt;code&gt;&#38;#39; &#38;#39;&lt;/code&gt; (&lt;i&gt;0x20&lt;/i&gt;) or &lt;code&gt;&#38;quot;\t&#38;quot;&lt;/code&gt; (&lt;i&gt;0x09&lt;/i&gt;). Or you update to Chart 2.403.9 or later and use pure CSV.&lt;/p&gt;

&lt;p&gt;The names of the first row are of course X-axis-labels, but &lt;code&gt;Chart&lt;/code&gt; takes care of that automatically and recognizes the following three rows as dataset0 .. dataset2. So let&#38;#39;s look at the entire code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Chart::Lines&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$file&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Chart::Lines&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;600&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_datafile&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$file&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;          &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Latest Numbers !&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;include_zero&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;true&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_grid_lines&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;true&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;precision&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;colors&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_grid_lines&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray60&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;misc&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray55&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;text&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray55&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;x_label&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray40&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;y_label&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray40&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt;        &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gray20&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;binmode&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;STDOUT&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;STDOUT&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;scalar_png&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last two code lines put the image binary into the command line, so after&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;perl ./script.pl data.tsv &#38;gt; chart.png&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;.. we get the chart in an image file of our choosing.&lt;/p&gt;

&lt;h3 id=&#34;Data-Set-Manipulation&#34;&gt;Data Set Manipulation&lt;/h3&gt;

&lt;p&gt;To take full advantage of this setup, our script should automatically adapt to different data set sizes. For that we have to get hold of the data, transform as needed and put it back in. It is simply a reference to an &lt;i&gt;array of arrays&lt;/i&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_datafile&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$file&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;clear_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# data transform&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This for instance would allow us to create color gradients or wheels of complementary colors of needed size matching the size of the dataset. How this works I already showed in a previous calendar leaf. But to give another practical example - wouldn&#38;#39;t it be nice to have data tables like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;o     Peter Paul Mary&lt;br /&gt;2020  30    40   80 &lt;br /&gt;2021  80    60   30 &lt;br /&gt;2020  50    30   60 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;i&gt;o&lt;/i&gt; symbol or any other placeholder is important because &lt;code&gt;Chart&lt;/code&gt; gets unhappy quickly when rows are of unequal length - even we pull out the first column before drawing. With this little preprocessing the first column of our data table is now appearing in the legend of the chart.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_datafile&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$file&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;clear_data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;map&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;@label&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_dataset&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$g&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;legend_labels&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@label&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Voil&#38;agrave;, our chart factory is humming away peacefully.&lt;/p&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Little scripts can produce piles of charts that are well labeled and and designer-colored, even if the incoming data sets have various sizes. Check all example code and images &lt;a href=&#34;https://github.com/lichtkind/Chart/tree/main/dev/example/advent&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-23T00:00:00Z</updated><category term="Perl"/><author><name>lichtkind</name></author></entry><entry><title>Building the Sleigh While Flying It</title><link href="http://perladvent.org/2022/2022-12-22.html"/><id>http://perladvent.org/2022/2022-12-22.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Building-the-Sleigh-While-Flying-It&#34;&gt;Building the Sleigh While Flying It&lt;/h2&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;B, a little help?&#38;quot;&lt;/i&gt; Santa&#38;#39;s voice echoed through the toymaker&#38;#39;s headquarters, its pitch a little higher than usual. Binky the Elf left her station and cracked open the boss&#38;#39;s door. &lt;i&gt;&#38;quot;What&#38;#39;s up, Nick?&#38;quot;&lt;/i&gt; she replied, nonchalantly. Santa was squinting at the monitor in front of him, where several lines of error messages kept flooding the terminal.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;I think there&#38;#39;s something wrong with the reindeers.&#38;quot;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;The famous Christmas Reindeers are, of course, robots. As a lover of all living things, Santa could never bring himself to force animals into such a strenuous journey each year. Besides, how else do you think they can travel that fast?&lt;/p&gt;

&lt;p&gt;Binky sighed and glanced over Santa&#38;#39;s right shoulder. The world population had just surpassed 8 billion, so they had to spend a good part of the year profiling and optimizing the reindeers&#38;#39; code for speed. &lt;i&gt;&#38;quot;I thought you tested it back at All Hallows Eve&#38;quot;&lt;/i&gt;, the elf cried. Santa looked down, his face redder than his coat. &lt;i&gt;&#38;quot;I was going to, but Jack took me trick or treating instead&#38;quot;&lt;/i&gt;, he muttered.&lt;/p&gt;

&lt;p&gt;Binky raised an eyebrow. With that kind of care, it was a Christmas Miracle this code compiled in the first place. Thinking of the kids, she decided not to pursue the argument and instead put her energy into finding and fixing the issue. The error messages were cryptic, at best:&lt;/p&gt;

&lt;pre&gt;
    &lt;code style=&#34;display: inline-block;white-space: normal;max-width:95%; word-break:break-all; word-wrap:break-word;&#34;&gt;
    Undefined subroutine &#38;Class::MOP::Class:::after called at /home/santaclaus/.plenv/versions/5.36.0/lib/perl5/site_perl/5.36.0/x86_64-linux/Class/MOP/Method/Wrapped.pm line 57.
    Reindeer::Prancer::_wrapped_dash_away(Reindeer::Prancer=HASH(0x1383a6160)) called at /home/santaclaus/.plenv/versions/5.36.0/lib/perl5/site_perl/5.36.0/x86_64-linux//Class/MOP/Method/Wrapped.pm line 97
    Reindeer::Prancer::dash_away(Reindeer::Prancer=HASH(0x1383a6160)) called at christmas.pl line 1225
    &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;Huh.&#38;quot;&lt;/i&gt;, the elf frowned. Reindeers were controlled by complex &lt;a href=&#34;https://metacpan.org/module/Moose&#34;&gt;Moose&lt;/a&gt; classes, but method modifiers such as &#38;#39;before&#38;#39;, &#38;#39;after&#38;#39; and &#38;#39;around&#38;#39; were pretty standard. It made no sense that &#38;quot;after&#38;quot; was not defined. Line 1225 of christmas.pl, was also pretty straightforward:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;symbol&#34;&gt;$reindeer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;dash_away&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Binky and Santa spent a little while staring at the source code. Everything looked fine, but the code was still failing. Finally, Binky broke the silence: &lt;i&gt;&#38;quot;Did you try dumping &lt;code&gt;$reindeer&lt;/code&gt; before that call?&#38;quot;&lt;/i&gt; she suggested. &lt;i&gt;&#38;quot;I did, but look!&#38;quot;&lt;/i&gt;, the old man scrolled up the terminal window and pointed at a line that said:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        $VAR1 = bless( {}, &#38;#39;Reindeer::Prancer&#38;#39; );&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;It&#38;#39;s just showing the bless() command, an empty hash reference and the class name. How am I supposed to work with that?&#38;quot;&lt;/i&gt; Santa whimpered. &lt;i&gt;&#38;quot;That&#38;#39;s because you&#38;#39;re using Data::Dumper, boss.&#38;quot;&lt;/i&gt; A faint smile crept into Binky&#38;#39;s lips. It wasn&#38;#39;t every day she was able to teach Father Christmas himself something new. She continued. &lt;i&gt;&#38;quot;Data::Dumper is best for serializing. If you want to inspect the data yourself, you should use &lt;a href=&#34;https://metacpan.org/module/Data::Printer&#34;&gt;Data::Printer&lt;/a&gt; instead.&#38;quot;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Santa Claus&#38;#39; eyes widened. &lt;i&gt;&#38;quot;Data::Printer? What kind of sorcery is that?&#38;quot;&lt;/i&gt; The elf signaled him to scooch over so she could reach the keyboard herself. As she typed &lt;code&gt;cpanm Data::Printer&lt;/code&gt;, she said: &lt;i&gt;&#38;quot;It&#38;#39;s a module that dumps variables in a way meant to be read by an actual human trying to debug code. Don&#38;#39;t worry, it&#38;#39;s super light and fast - zero deps and all. See? It&#38;#39;s already installed.&#38;quot;&lt;/i&gt; Then she fired up the editor and replaced the line that said:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$reindeer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;DDP&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$reindeer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They gave it another go and the result was quite different:&lt;/p&gt;

&lt;pre&gt;
    &lt;code&gt;
    &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer::Prancer&lt;/span&gt;  &lt;span style=&#34;color:#66D9EF&#34;&gt;{&lt;/span&gt;
         &lt;span&gt;parents:&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer&lt;/span&gt;
         &lt;span&gt;roles (1):&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;FlyingMagic&lt;/span&gt;
         &lt;span&gt;attributes (2):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;name&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; sleigh&lt;/span&gt;
         &lt;span&gt;public methods (24):&lt;/span&gt;
             &lt;span style=&#34;color:#82AAFF&#34;&gt;dash_away&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; DESTROY&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; meta&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; new&lt;/span&gt;
             &lt;span&gt;Carp:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;confess&lt;/span&gt;
             &lt;span&gt;Class::MOP::Class:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;:after&lt;/span&gt;
             &lt;span&gt;FlyingMagic:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;liftoff&lt;/span&gt;
             &lt;span&gt;Moose:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;after&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;around&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;augment&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;before&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;extends&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;has&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;inner&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;override&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;super&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;with&lt;/span&gt;
             &lt;span&gt;Moose::Object:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;BUILDALL&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;BUILDARGS&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;DEMOLISHALL&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;does&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;DOES&lt;/span&gt;, &lt;span style=&#34;color:#82AAFF&#34;&gt;dump&lt;/span&gt;
             &lt;span&gt;Scalar::Util:&lt;/span&gt;
                 &lt;span style=&#34;color:#82AAFF&#34;&gt;blessed&lt;/span&gt;
         &lt;span&gt;private methods (1):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;_build_name&lt;/span&gt;
         &lt;span&gt;method modifiers (1):&lt;/span&gt;
             &lt;span&gt;after dash_away&lt;/span&gt; &lt;span style=&#34;color:#FF5370&#34;&gt;&#38;lt;undefined coderef&#38;gt;&lt;/span&gt;
         &lt;span&gt;internals: &lt;/span&gt;&lt;span style=&#34;color:#66D9EF&#34;&gt;{}&lt;/span&gt;
     &lt;span style=&#34;color:#66D9EF&#34;&gt;}&lt;/span&gt;
  &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;The terminal lit up like a Christmas Tree. They could see the full class hierarchy, applied roles, attributes, public and private methods - everything! Santa&#38;#39;s eyes sparkled. &lt;i&gt;&#38;quot;Ho! Ho! Ho! I know what&#38;#39;s wrong.&#38;quot;&lt;/i&gt; He pointed at the line that said &lt;code&gt;after dash_away: &#38;lt;undefined coderef&#38;gt;&lt;/code&gt; in bright red. They searched the source code for &lt;code&gt;&#38;#39;after &#38;quot;dash_away&#38;quot;&#38;#39;&lt;/code&gt; and quickly found the only entry, that read:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;after&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;dash_away&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;&#38;amp;lifftoff&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They took another look at the Data::Printer output searching for that method. Santa quickly spotted it coming from the &lt;code&gt;FlyingMagic&lt;/code&gt; role, but it was written differently. &lt;i&gt;&#38;quot;A typo! Someone was naughty on that code review.&#38;quot;&lt;/i&gt; They fixed the typo and ran it again. It worked! One by one the reindeers started whirring. Santa was about to jump on the sleigh for a final test-drive when the elf interrupted the program. &lt;i&gt;&#38;quot;What is it, B?&#38;quot;&lt;/i&gt; the old man asked.&lt;/p&gt;

&lt;p&gt;Binky was staring at the terminal again. &lt;i&gt;&#38;quot;It&#38;#39;s leaking memory. The way things are, the sleigh will crash before you even reach the Atlantic. Hold on.&#38;quot;&lt;/i&gt; The elf added a bunch of &lt;code&gt;p()&lt;/code&gt; statements throughout the code. Santa Claus looked bewildered. &lt;i&gt;&#38;quot;What are you doing? There will be so much stuff in the output we won&#38;#39;t be able to make any of it out!&#38;quot;&lt;/i&gt;, he scoffed.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;Sure we will.&#38;quot;&lt;/i&gt; Binky replied without taking her eyes off the monitor. &lt;i&gt;&#38;quot;We&#38;#39;ll control what prints what on &lt;a href=&#34;https://metacpan.org/module/Data::Printer#The-.dataprinter-configuration-file&#34;&gt;the .dataprinter file&lt;/a&gt;&#38;quot;&lt;/i&gt;. She created a new file called &#38;quot;.dataprinter&#38;quot; on the root of the project path, then made it look something like this:&lt;/p&gt;

&lt;pre class=&#34;code-listing&#34;&gt;
    &lt;code class=&#34;code&#34;&gt;
    &lt;span class=&#34;single&#34;&gt;show_refcount&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;1&lt;/span&gt;
    &lt;span class=&#34;single&#34;&gt;theme&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Material&lt;/span&gt;

    &lt;span class=&#34;symbol&#34;&gt;[Sleigh::Engine]&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;class.expand&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;0&lt;/span&gt;
    
    &lt;span class=&#34;symbol&#34;&gt;[Toys::Storage::MagicBag]&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;filters&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;DB&lt;/span&gt;
    
    &lt;span class=&#34;symbol&#34;&gt;[Reindeer]&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;class.stringify&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;0&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;class.show_wrapped&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;0&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;class.inherited&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;none&lt;/span&gt;
        &lt;span class=&#34;single&#34;&gt;output&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;/var/log/christmas/reindeer.data&lt;/span&gt;
    &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Binky went on to explain that you could place global settings for Data::Printer at the top of that file, like setting a theme and showing refcounts, then create more specific rules that apply only to certain caller packages. In this case, any &lt;code&gt;p()&lt;/code&gt; statements made inside &lt;code&gt;Sleigh::Engine&lt;/code&gt; would not expand objects, showing only the class name and (as per the global setting) the refcount. On the other hand, calls to &lt;code&gt;p()&lt;/code&gt; inside &lt;code&gt;Toys::Storage::MagicBag&lt;/code&gt; would be subject to all the filters set on &lt;a href=&#34;https://metacpan.org/module/Data::Printer::Filters::DB&#34;&gt;Data::Printer::Filters::DB&lt;/a&gt;, useful to see database connection statuses, prepared statements, result sources and sets from DBI, DBIx::Class and more.&lt;/p&gt;

&lt;p&gt;Finally, calls to &lt;code&gt;p()&lt;/code&gt; made inside &lt;code&gt;Reindeer.pm&lt;/code&gt; would not attempt to stringify objects that have a subroutine &lt;code&gt;as_string&lt;/code&gt;, &lt;code&gt;to_string&lt;/code&gt; or similar, nor will they show wrapped method modifiers or methods inherited from parent classes. Even so, that particular output is in a hot codepath and can get pretty big, so instead of printing to STDERR, it will write to the custom &lt;code&gt;/var/log/christmas/reindeer.data&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&#38;quot;We could even put all those settings in a custom profile package and upload it to CPAN or whatever, but right now a .dataprinter file is more than enough.&#38;quot;&lt;/i&gt; They tried running the program again and, sure enough, the output read:&lt;/p&gt;

&lt;pre&gt;
    &lt;code&gt;
    &lt;span style=&#34;color:#C792EA&#34;&gt;Sleigh&lt;/span&gt; (refcount: 10)
    &lt;span style=&#34;color:#C792EA&#34;&gt;Sleigh&lt;/span&gt; (refcount: 10)
    &lt;span style=&#34;color:#C792EA&#34;&gt;Sleigh&lt;/span&gt; (refcount: 10)
    &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Santa was puzzled. &lt;i&gt;&#38;quot;10 refcounts on the sleigh? We must have a circular reference somewhere. What&#38;#39;s going on on that Reindeer log file?&#38;quot;&lt;/i&gt; Binky opened it, but it looked pretty much the same: several reindeer objects just like before, except this time without the inherited methods but with a refcount next to each data, just like they asked:&lt;/p&gt;

&lt;pre&gt;
    &lt;code&gt;
    &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer::Vixen&lt;/span&gt;  &lt;span style=&#34;color:#66D9EF&#34;&gt;{&lt;/span&gt;
         &lt;span&gt;parents:&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer&lt;/span&gt;
         &lt;span&gt;roles (1):&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;FlyingMagic&lt;/span&gt;
         &lt;span&gt;attributes (2):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;name&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; sleigh&lt;/span&gt;
         &lt;span&gt;public methods (4):&lt;/span&gt;
             &lt;span style=&#34;color:#82AAFF&#34;&gt;dash_away&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; DESTROY&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; meta&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; new&lt;/span&gt;
         &lt;span&gt;private methods (1):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;_build_name&lt;/span&gt;
         &lt;span&gt;internals: &lt;/span&gt;&lt;span style=&#34;color:#66D9EF&#34;&gt;{&lt;/span&gt;
             &lt;span style=&#34;color:#82AAFF&#34;&gt;sleigh&lt;/span&gt;    &lt;span style=&#34;color:#C792EA&#34;&gt;Sleigh&lt;/span&gt; (refcount: 10)
         &lt;span style=&#34;color:#66D9EF&#34;&gt;}&lt;/span&gt;
     &lt;span style=&#34;color:#66D9EF&#34;&gt;}&lt;/span&gt;
  &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Santa sighed. &lt;i&gt;&#38;quot;If only that Data::Printer of yours could signal weak references...&#38;quot;&lt;/i&gt; Binky&#38;#39;s eyes widened as she stared at him. &lt;i&gt;&#38;quot;Nick, you&#38;#39;re a genius!&#38;quot;&lt;/i&gt; The old man chuckled. &lt;i&gt;&#38;quot;Me? What did I do?&#38;quot;&lt;/i&gt; The elf went on. &lt;i&gt;&#38;quot;Data::Printer DOES show when it&#38;#39;s looking at a weak ref. The fact that we don&#38;#39;t see it means that Sleigh object right there was NOT weakened.&#38;quot;&lt;/i&gt; They opened the reindeer class in the editor and replaced the line that read:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;sleigh&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Sleigh&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;sleigh&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Sleigh&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;weak_ref&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They fired up the program again. The reindeers whirred and clanked for a few seconds, then Rudolph&#38;#39;s nose lit up, signaling the restart was complete and they were all ready to fly. Santa&#38;#39;s heartbeat kicked up a notch as Binky opened the logs to see what it showed:&lt;/p&gt;

&lt;pre&gt;
    &lt;code&gt;
    &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer::Vixen&lt;/span&gt;  &lt;span style=&#34;color:#66D9EF&#34;&gt;{&lt;/span&gt;
         &lt;span&gt;parents:&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;Reindeer&lt;/span&gt;
         &lt;span&gt;roles (1):&lt;/span&gt; &lt;span style=&#34;color:#C792EA&#34;&gt;FlyingMagic&lt;/span&gt;
         &lt;span&gt;attributes (2):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;name&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; sleigh&lt;/span&gt;
         &lt;span&gt;public methods (4):&lt;/span&gt;
             &lt;span style=&#34;color:#82AAFF&#34;&gt;dash_away&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; DESTROY&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; meta&lt;/span&gt;,&lt;span style=&#34;color:#82AAFF&#34;&gt; new&lt;/span&gt;
         &lt;span&gt;private methods (1):&lt;/span&gt; &lt;span style=&#34;color:#82AAFF&#34;&gt;_build_name&lt;/span&gt;
         &lt;span&gt;internals: &lt;/span&gt;&lt;span style=&#34;color:#66D9EF&#34;&gt;{&lt;/span&gt;
             &lt;span style=&#34;color:#82AAFF&#34;&gt;sleigh&lt;/span&gt;    &lt;span style=&#34;color:#C792EA&#34;&gt;Sleigh&lt;/span&gt; &lt;span style=&#34;color:#90B55A&#34;&gt;(weak)&lt;/span&gt;
         &lt;span style=&#34;color:#66D9EF&#34;&gt;}&lt;/span&gt;
     &lt;span style=&#34;color:#66D9EF&#34;&gt;}&lt;/span&gt;
  &lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;The sleigh references were weak and no refcount was showing. &lt;i&gt;&#38;quot;Yes!&#38;quot;&lt;/i&gt; the elf fell back into her chair and breathed a sigh of relief. &lt;i&gt;&#38;quot;Do we remove the &lt;code&gt;p()&lt;/code&gt; statements now that everything is fine?&#38;quot;&lt;/i&gt; asked Santa. &lt;i&gt;&#38;quot;We can, sure - but if you think they&#38;#39;re in good debugging spots you can just add &lt;code&gt;quiet = 1&lt;/code&gt; to each section of the .dataprinter file and any calls to &lt;code&gt;p()&lt;/code&gt; will quickly return not printing anything. We can even add a &lt;code&gt;live_update = 1&lt;/code&gt; and Data::Printer will automatically watch the .dataprinter file and reload it whenever we change it without needing to restart the program.&#38;quot;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;The old man thanked his friend as she rose up to leave. Binky was almost at the door when she turned and realized Santa was still at the computer. &lt;i&gt;&#38;quot;You&#38;#39;re gonna play with the output colors and &lt;a href=&#34;https://metacpan.org/module/Data::Printer::Theme&#34;&gt;make a new theme for Data::Printer&lt;/a&gt; now, aren&#38;#39;t you?&#38;quot;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Santa grinned. This was going to be a Merry Christmas after all.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-22T00:00:00Z</updated><category term="Perl"/><author><name>Breno G. de Oliveira</name></author></entry><entry><title>Lapland Packaging Department - Part 2</title><link href="http://perladvent.org/2022/2022-12-21.html"/><id>http://perladvent.org/2022/2022-12-21.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;After getting to work on his second day, Tonttu quickly downloaded the &lt;a href=&#34;https://metacpan.org/module/Carton&#34;&gt;Carton&lt;/a&gt; module&#38;#39;s tarball. This was the chosen module to make the installation and packaging of other modules and projects easier.&lt;/p&gt;

&lt;p&gt;Carton is capable of dependency handling, can download the source tarballs for modules and last but not least, can create a portable package for any project. This package can be copied to any machine and &lt;a href=&#34;https://metacpan.org/module/Carton&#34;&gt;Carton&lt;/a&gt; will install all modules automatically, without the need for an internet connection. The nisse started to do some testing and cooked up the following proof of concept for Santa for the first part:&lt;/p&gt;

&lt;p&gt;Tonttu made sure first, that Carton is installed on all servers in the warehouse. He used the manual compilation method he had jotted down the day before.&lt;/p&gt;

&lt;p&gt;After that he wrote the following guide for his busy elf colleagues:&lt;/p&gt;

&lt;h3 id=&#34;Task-1.---Preparing-the-distribution&#34;&gt;Task 1. - Preparing the distribution&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;cpanfile&lt;/code&gt; for your project, listing all the used modules (of course only the ones not part of the Perl core, but installed extra). List the minimum required Perl version for your project (if any) in the first line.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;# cpanfile&lt;br /&gt;requires &#38;#39;perl&#38;#39;, &#38;#39;5.20.0&#38;#39;;&lt;br /&gt;requires &#38;#39;Getopt::Long&#38;#39;;&lt;br /&gt;requires &#38;#39;Data::Dumper&#38;#39;;&lt;br /&gt;requires &#38;#39;Log::Log4perl&#38;#39;;&lt;br /&gt;requires &#38;#39;MIME::Lite&#38;#39;;&lt;br /&gt;requires &#38;#39;MIME::Types&#38;#39;;&lt;br /&gt;requires &#38;#39;Mail::Address&#38;#39;;&lt;br /&gt;requires &#38;#39;Net::SCP&#38;#39;;&lt;br /&gt;requires &#38;#39;JSON&#38;#39;;&lt;br /&gt;requires &#38;#39;DBI&#38;#39;;&lt;br /&gt;requires &#38;#39;Excel::Writer::XLSX&#38;#39;;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, only a handful of modules are in there, &lt;a href=&#34;https://metacpan.org/module/Carton&#34;&gt;Carton&lt;/a&gt; will automatically take care of the dependencies.&lt;/p&gt;

&lt;p&gt;Next step is to &lt;code&gt;carton install&lt;/code&gt; the modules inside the &lt;code&gt;local/&lt;/code&gt; directory.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ carton install&lt;br /&gt;Installing modules using /home/cabox/workspace/projects/test_carton/cpanfile&lt;br /&gt;Successfully installed Archive-Zip-1.68&lt;br /&gt;Successfully installed Excel-Writer-XLSX-1.09&lt;br /&gt;Successfully installed Net-SSH-0.09&lt;br /&gt;Successfully installed String-ShellQuote-1.04&lt;br /&gt;Successfully installed Net-SCP-0.08&lt;br /&gt;5 distributions installed&lt;br /&gt;Complete! Modules were installed into /home/cabox/workspace/projects/test_carton/local&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that after this step a file named &lt;code&gt;cpanfile.snapshot&lt;/code&gt; has been generated, with all the modules and dependencies managed by Carton. As You can see from the below example there are way more modules in this file than in our list in the &lt;code&gt;cpanfile&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ cat cpanfile.snapshot&lt;br /&gt;# carton snapshot format: version 1.0&lt;br /&gt;DISTRIBUTIONS&lt;br /&gt;&#38;nbsp;&#38;nbsp;Archive-Zip-1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pathname: P/PH/PHRED/Archive-Zip-1.68.tar.gz&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;provides:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::Archive 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::BufferedFileHandle 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::DirectoryMember 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::FileMember 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::Member 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::MemberRead 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::MockFileHandle 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::NewFileMember 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::StringMember 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::Tree 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip::ZipFileMember 1.68&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;requirements:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Compress::Raw::Zlib 2.017&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Encode 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;ExtUtils::MakeMaker 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Basename 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Copy 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Find 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Path 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Spec 0.80&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Temp 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;IO::File 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;IO::Handle 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;IO::Seekable 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Time::Local 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;perl 5.006&lt;br /&gt;&#38;nbsp;&#38;nbsp;Excel-Writer-XLSX-1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pathname: J/JM/JMCNAMARA/Excel-Writer-XLSX-1.09.tar.gz&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;provides:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Area 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Bar 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Column 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Doughnut 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Line 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Pie 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Radar 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Scatter 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chart::Stock 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Chartsheet 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Drawing 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Examples 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Format 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::App 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Comments 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::ContentTypes 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Core 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Custom 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Metadata 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Packager 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Relationships 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::SharedStrings 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Styles 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Table 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::Theme 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::VML 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Package::XMLwriter 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Shape 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Utility 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Workbook 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Excel::Writer::XLSX::Worksheet 1.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;requirements:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Archive::Zip 1.3&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;ExtUtils::MakeMaker 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;File::Temp 0.19&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;IO::File 1.14&lt;br /&gt;&#38;nbsp;&#38;nbsp;Net-SCP-0.08.reprise&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pathname: I/IV/IVAN/Net-SCP-0.08.reprise.tar.gz&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;provides:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Net::SCP 0.08&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;requirements:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;ExtUtils::MakeMaker 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;IO::Handle 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Net::SSH 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;String::ShellQuote 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;Net-SSH-0.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pathname: I/IV/IVAN/Net-SSH-0.09.tar.gz&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;provides:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;Net::SSH 0.09&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;requirements:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;ExtUtils::MakeMaker 0&lt;br /&gt;&#38;nbsp;&#38;nbsp;String-ShellQuote-1.04&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;pathname: R/RO/ROSCH/String-ShellQuote-1.04.tar.gz&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;provides:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;String::ShellQuote 1.04&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;requirements:&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;ExtUtils::MakeMaker 0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don&#38;#39;t forget to exclude the &lt;code&gt;local/&lt;/code&gt; directory and add the files &lt;code&gt;cpanfile&lt;/code&gt; and &lt;code&gt;cpanfile.snapshot&lt;/code&gt; to your version control system!&lt;/p&gt;

&lt;p&gt;At this point we have a package, which is not really portable. To make it portable, run&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ carton bundle&lt;br /&gt;Bundling modules using /home/cabox/workspace/projects/test_carton/cpanfile&lt;br /&gt;Copying P/PH/PHRED/Archive-Zip-1.68.tar.gz&lt;br /&gt;Copying J/JM/JMCNAMARA/Excel-Writer-XLSX-1.09.tar.gz&lt;br /&gt;Copying I/IV/IVAN/Net-SCP-0.08.reprise.tar.gz&lt;br /&gt;Copying I/IV/IVAN/Net-SSH-0.09.tar.gz&lt;br /&gt;Copying R/RO/ROSCH/String-ShellQuote-1.04.tar.gz&lt;br /&gt;Writing /home/cabox/workspace/projects/test_carton/vendor/cache/modules/02packages.details.txt.gz&lt;br /&gt;Complete! Modules were bundled into /home/cabox/workspace/projects/test_carton/vendor/cache&lt;br /&gt;It will bundle your tar archives into the vendor/ directory.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add &lt;code&gt;vendor&lt;/code&gt; to your VCS or don&#38;#39;t, it&#38;#39;s up to you.&lt;/p&gt;

&lt;p&gt;Now we are ready to deploy the package to a different machine.&lt;/p&gt;

&lt;h3 id=&#34;Task-2:-Deploying-your-Package-to-the-Remote-Machines&#34;&gt;Task 2: Deploying your Package to the Remote Machines&lt;/h3&gt;

&lt;p&gt;Copy the whole directory to the desired directory on the target systems.&lt;/p&gt;

&lt;p&gt;This is the directory structure you should see (without your own stuff):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;.&lt;br /&gt;|-- cpanfile&lt;br /&gt;|-- cpanfile.snapshot&lt;br /&gt;|-- ...  #Your stuff here&lt;br /&gt;|-- ...	 #Your stuff here&lt;br /&gt;`-- vendor&lt;br /&gt;&#38;nbsp;`-- cache&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;|-- authors&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;`-- modules&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it&#38;#39;s time to install the modules using Carton (which has been previously installed by Tonttu):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ carton install --deployment cached&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will use the module tarballs from the &lt;code&gt;vendor/&lt;/code&gt; directory and create &lt;code&gt;local/&lt;/code&gt; with the installed modules.&lt;/p&gt;

&lt;p&gt;If therea are no errors, you may remove the &lt;code&gt;vendor/&lt;/code&gt; directory (optional).&lt;/p&gt;

&lt;p&gt;Santa reviewed the proof of concept and was proud of Tonttu for doing such a great job.&lt;/p&gt;

&lt;p&gt;After sharing the how-to, all the elves started to use the &lt;a href=&#34;https://metacpan.org/module/Carton&#34;&gt;Carton&lt;/a&gt; packaging module and their job got a lot easier.&lt;/p&gt;

&lt;p&gt;Santa was cheerful and satisfied, as the whole Packaging Department could fulfill more children&#38;#39;s wishes much much faster than before.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-21T00:00:00Z</updated><category term="Perl"/><author><name>Csaba Sim&#225;ndi</name></author></entry><entry><title>Lapland Packaging Department - Part 1</title><link href="http://perladvent.org/2022/2022-12-20.html"/><id>http://perladvent.org/2022/2022-12-20.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Once upon a time in the far North in Lapland (more precisely in Korvatunturi), Tonttu the nisse joined the Lapland Packaging Department after a successful series of interviews with Joulupukki -- aka Santa -- himself. Tonntu got the challenging task to make the Packaging Department&#38;#39;s work more effective. On his very first day in the middle of November he was checking the IT infrastructure in the warehouse. He noticed the network is segmented and only one machine had connection to the internet through a proxy.&lt;/p&gt;

&lt;p&gt;There was not much time left until Advent so he decided to stick with Perl, his favourite programming language.&lt;/p&gt;

&lt;p&gt;&#38;quot;Perl is capable of everything by itself, anyway&#38;quot;, he thought.&lt;/p&gt;

&lt;p&gt;Unfortunately there was no chance to use tools like &lt;a href=&#34;https://metacpan.org/module/cpan&#34;&gt;cpan&lt;/a&gt; or &lt;a href=&#34;https://metacpan.org/module/App::cpanminus&#34;&gt;App::cpanminus&lt;/a&gt; only on that single machine connected to the internet. And that connection worked only when the &lt;code&gt;http_proxy&lt;/code&gt; and &lt;code&gt;https_proxy&lt;/code&gt; were explicitly set beforehand.&lt;/p&gt;

&lt;p&gt;First of all he needed a solution to be able to use at least a handful of modules to accomplish his work.&lt;/p&gt;

&lt;p&gt;&#38;quot;Why not compile the required modules from source downloaded from CPAN?&#38;quot;, he asked himself.&lt;/p&gt;

&lt;p&gt;It sounded like a good starting point. He immediately made his hands dirty.&lt;/p&gt;

&lt;p&gt;Tonttu quickly jotted down a small how-to:&lt;/p&gt;

&lt;p&gt;This method can be used to compile any Perl module manually on Linux!&lt;/p&gt;

&lt;p&gt;First of all make sure, that &lt;code&gt;PERL5LIB&lt;/code&gt; is loaded. If not, load it with export &lt;code&gt;PERL5LIB=/path/to/your/perl&lt;/code&gt; (especially if you have Perl installed to a custom location).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ echo $PERL5LIB&lt;br /&gt;/home/cabox/perl5/lib/perl5&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the output is empty, that means &lt;code&gt;PERL5LIB&lt;/code&gt; is not loaded (most probably Perl is installed into a custom location). So let&#38;#39;s load it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;export PERL5LIB=/path/to/your/perl&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Second, we need to download the module from CPAN. Let&#38;#39;s demonstrate the process with &lt;a href=&#34;https://metacpan.org/module/Pod::Advent&#34;&gt;Pod::Advent&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Download the tarball for the installation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ wget https://cpan.metacpan.org/authors/id/D/DA/DAVIDRW/Pod-Advent-0.24.tar.gz&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Untar the archive:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;tar -xzvf Pod-Advent-0.24.tar.gz&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Switch to the directory of the module&#38;#39;s source:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ cd Pod-Advent-0.24&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Execute Makefile.PL with Perl.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ perl Makefile.PL&lt;br /&gt;Checking if your kit is complete...&lt;br /&gt;Looks good&lt;br /&gt;Generating a Unix-style Makefile&lt;br /&gt;Writing Makefile for Pod::Advent&lt;br /&gt;Writing MYMETA.yml and MYMETA.json&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then execute &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;make install&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;$ make&lt;br /&gt;cp lib/Pod/Advent.pm blib/lib/Pod/Advent.pm&lt;br /&gt;cp bin/pod2advent blib/script/pod2advent&lt;br /&gt;&#38;quot;/home/cabox/perl5/perlbrew/perls/perl-5.28.0/bin/perl&#38;quot; -MExtUtils::MY -e &#38;#39;MY-&#38;gt;fixin(shift)&#38;#39; -- blib/script/pod2advent&lt;br /&gt;Manifying 1 pod document&lt;br /&gt;Manifying 1 pod document&lt;br /&gt;&lt;br /&gt;$ make install                                                                       &lt;br /&gt;Manifying 1 pod document&lt;br /&gt;Manifying 1 pod document&lt;br /&gt;Appending installation info to /home/cabox/perl5/lib/perl5/x86_64-linux/perllocal.pod&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the case of a more complicated module, tests might fail. You might be presented with errors in the output, or in the worst case, you might face dependency hell. DISCLAIMER: To avoid dependency hell or other errors upon module installation it is recommended to use &lt;a href=&#34;https://metacpan.org/module/cpan&#34;&gt;cpan&lt;/a&gt; or &lt;a href=&#34;https://metacpan.org/module/cpanm&#34;&gt;cpanm&lt;/a&gt; wherever and whenever possible.&lt;/p&gt;

&lt;p&gt;Tonttu knew that installing modules this way is cumbersome, but sometimes, in difficult environments, these steps can come handy.&lt;/p&gt;

&lt;p&gt;Santa took a look at the how-to and told Tonttu kindly: &#38;quot;Not bad, especially on your first day, but I am sure you are able to improve it. Try to think about extending the solution.&#38;quot;&lt;/p&gt;

&lt;p&gt;Tonttu went to the community room and started knitting -- that was his favorite hobby and it helped him to think.&lt;/p&gt;

&lt;p&gt;After finishing a scarf with red nosed reindeers, the solution was already in his head. Tomorrow he will try it out, but that is already another story.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-20T00:00:00Z</updated><category term="Perl"/><author><name>Csaba Sim&#225;ndi</name></author></entry><entry><title>Find known, reported vulnerabilities in the modules you use</title><link href="http://perladvent.org/2022/2022-12-19.html"/><id>http://perladvent.org/2022/2022-12-19.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;How do you know that you are up-to-date on security advisories for perl and CPAN modules? &lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt; and its &lt;b&gt;cpan-audit&lt;/b&gt; program can do that for you:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    % cpan CPAN::Audit
    % cpan-audit installed&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You end up with a list of reports of known vulnerabilities for everything in your &lt;code&gt;@INC&lt;/code&gt;. Fix some of those by upgrading modules, using a more modern replacement, or, even better fix the problem and send that upstream.&lt;/p&gt;

&lt;p&gt;These reports come mostly from &lt;a href=&#34;https://www.cve.org&#34;&gt;MITRE&lt;/a&gt; and its library of Common Vulnerabilities and Exposures, or just CVE, that it&#38;#39;s developed since 1999. All of this is pre-digested and arranged into &lt;code&gt;CPAN::Audit::DB&lt;/code&gt;, which comes with the &lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt; distribution.&lt;/p&gt;

&lt;h3 id=&#34;Check-a-module&#34;&gt;Check a module&lt;/h3&gt;

&lt;p&gt;If you are interested in a particular module, you can check that too. For example, &lt;a href=&#34;https://metacpan.org/module/DBI&#34;&gt;DBI&lt;/a&gt; has had several reports over its history:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        % cpan-audit module DBI

          * CPANSA-DBI-2014-01
                DBD::File drivers open files from folders other than
                specifically passed using the f_dir attribute.

                Affected range: &#38;lt;1.632
                Fixed range: &#38;gt;=1.632

                References:
                https://metacpan.org/changes/distribution/DBI
                https://rt.cpan.org/Public/Bug/Display.html?id=99508

          * CPANSA-DBI-2020-01
                A buffer overflow was found in perl-DBI &#38;lt; 1.643 in DBI.xs. A
                local attacker who is able to supply a string longer than 300
                characters could cause an out-of-bounds write, affecting the
                availability of the service or integrity of data.

                Affected range: &#38;lt;1.643
                Fixed range: &#38;gt;=1.643

                CVEs: CVE-2020-14393

                References:
                https://metacpan.org/changes/distribution/DBI
                https://bugzilla.redhat.com/show_bug.cgi?id=1877409

        ... many more advisories ...

        Total advisories found: 9&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Those are the advisories for DBI for the entire history of the Universe, and all of those have been patched already and you don&#38;#39;t care about them.&lt;/p&gt;

&lt;p&gt;Specify a version to see advisories the apply to just that version. The current version of &lt;a href=&#34;https://metacpan.org/module/DBI&#34;&gt;DBI&lt;/a&gt;, 1.643 as I write this, so try that. There are no open (known) vulnerabilities:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        % cpan-audit module DBI 1.643
        No advisories found&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That second argument can also be a range, such as &lt;code&gt;&#38;gt;1.600&lt;/code&gt;. Ensure that you quote the range since &lt;code&gt;&#38;gt;&lt;/code&gt; and &lt;code&gt;&#38;lt;&lt;/code&gt; are shell metacharacters:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        % cpan-audit module DBI &#38;#39;&#38;gt;1.600&#38;#39;
        ... eight advisories ...
        Total advisories found: 8&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Command-line use is nice, but you&#38;#39;re more likely to use this in some automated program to continuously check your installation. The exit code tells you what &lt;b&gt;cpan-audit&lt;/b&gt; found. If you get 0, there were no advisories found. If you get a number larger than 64, subtract 64 to get the number of advisories:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        % cpan-audit module DBI &#38;#39;&#38;gt;1.600&#38;#39;
        ... eight advisories ...
        Total advisories found: 8
        % echo $?
        72&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;How-it-works&#34;&gt;How it works&lt;/h3&gt;

&lt;p&gt;&#38;#x412;&#38;#x44F;&#38;#x447;&#38;#x435;&#38;#x441;&#38;#x43B;&#38;#x430;&#38;#x432; &#38;#x422;&#38;#x438;&#38;#x445;&#38;#x430;&#38;#x43D;&#38;#x43E;&#38;#x432;&#38;#x441;&#38;#x43A;&#38;#x438;&#38;#x439; (vti on CPAN) created &lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt; to collate information from MITRE (the repository of CVEs), namespace mappings from PAUSE, and version data from MetaCPAN. He put that all together so he could present to you the vulnerabilities in a useful way.&lt;/p&gt;

&lt;p&gt;The advisory data are actually kept in a separate repository, &lt;a href=&#34;https://github.com/briandfoy/cpan-security-advisory&#34;&gt;cpan-security-advisory&lt;/a&gt;. Each advisory references some vulnerability, notes the affected version, and tracks some other information. These are kept in YAML files for each distribution.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt; digests those YAML files to create &lt;code&gt;CPAN::Audit::DB&lt;/code&gt; so that each release contains all of the vulnerability data. Once you install &lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt;, perhaps on an isolated machine with no network access, you have everything you need. There&#38;#39;s no extra networking, downloading, and so on.&lt;/p&gt;

&lt;p&gt;When you run &lt;b&gt;cpan-audit&lt;/b&gt;, it selects from that database just the information appropriate for you.&lt;/p&gt;

&lt;h3 id=&#34;Contribute&#34;&gt;Contribute!&lt;/h3&gt;

&lt;p&gt;A small group of people are revitalizing &lt;a href=&#34;https://metacpan.org/module/CPAN::Audit&#34;&gt;CPAN::Audit&lt;/a&gt;, and there&#38;#39;s always room for more. There&#38;#39;s work appropriate for all skill levels.&lt;/p&gt;

&lt;p&gt;This project only useful if it has up-to-date and correct data. A large part of the effort involves keeping up-to-date with vulnerabilities, and a lot of that is boring, manual work. Bite off some small chunks to earn some of those [GitHub badges](https://github.com/Schweinepriester/github-profile- achievements). The &lt;a href=&#34;https://github.com/briandfoy/cpan-security-advisory/blob/master/CONTRIBUTING.md&#34;&gt;CONTRIBUTING&lt;/a&gt; docs are a good place to start.&lt;/p&gt;

&lt;p&gt;We&#38;#39;re also looking to revamp how we collate the data to make it easier to work with. We&#38;#39;ve started tracking vulnerabilities in external libraries, such as bootstrap, that some distributions include. That&#38;#39;s not quite ready, but it&#38;#39;s getting close.&lt;/p&gt;

&lt;p&gt;Finally, you can just use &lt;b&gt;cpan-audit&lt;/b&gt; and let us know how it works for you, what else you need to accomplish your task, and how else we can help you track this information. The &lt;a href=&#34;https://github.com/briandfoy/cpan-audit/discussions&#34;&gt;Discussions section of CPAN::Audit&#38;#39;s repo&lt;/a&gt; is a good way to give non-issue feedback.&lt;/p&gt;

&lt;h3 id=&#34;Links&#34;&gt;Links&lt;/h3&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/briandfoy/cpan-audit&#34;&gt;CPAN::Audit&lt;/a&gt; repository&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/briandfoy/cpan-security-advisory&#34;&gt;CPAN Security Advisory repository&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An RSS feed for &lt;a href=&#34;https://www.theperlreview.com/perl-cve-atom.xml&#34;&gt;perl search results from MITRE&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;</summary><updated>2022-12-19T00:00:00Z</updated><category term="Perl"/><author><name>brian d foy</name></author></entry><entry><title>TWVycnkgQ2hyaXN0bWFzIDop</title><link href="http://perladvent.org/2022/2022-12-18.html"/><id>http://perladvent.org/2022/2022-12-18.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h3 id=&#34;Perl-Birthday-Party&#34;&gt;Perl Birthday Party&lt;/h3&gt;

&lt;p&gt;On the 18th of December, to celebrate Perl&#38;#39;s birthday, the elves organized a big party with cakes, waffles, pancakes and maple syrup.&lt;/p&gt;

&lt;p&gt;They partied like crazy but only until exactly midnight when everyone went to bed.&lt;/p&gt;

&lt;p&gt;The day after, the elves walked to North Pole warehouse. To open the door and disable the alarm, as every day, they called the dedicated elf &#38;quot;Spof&#38;quot; to enter the code. He typed the code and the security LCD printed &#38;quot;ERROR&#38;quot;.&lt;/p&gt;

&lt;p&gt;- Type it again, said another elf&lt;/p&gt;

&lt;p&gt;He proceeded and, once again, got &#38;quot;ERROR&#38;quot;.&lt;/p&gt;

&lt;p&gt;- We are bad!&lt;/p&gt;

&lt;p&gt;Then they looked at Spof, his face was all red and his eyes were all dizzy... They remembered that Spof drank a lot of maple syrup during the past day party, something like 5 glasses. And if you are not aware, elves should drink maple syrup with parsimony because else it drives them mad!&lt;/p&gt;

&lt;p&gt;- What is the code? they asked&lt;/p&gt;

&lt;p&gt;- TWVycnkgQ2hyaXN0bWFzIDop&lt;/p&gt;

&lt;p&gt;- Are you sure?&lt;/p&gt;

&lt;p&gt;- WWVz&lt;/p&gt;

&lt;h3 id=&#34;Deciphering-the-code&#34;&gt;Deciphering the code&lt;/h3&gt;

&lt;p&gt;One of the elves has a little experience with IT and he immediately thought he would test &lt;a href=&#34;https://metacpan.org/module/MIME::Base64&#34;&gt;MIME::Base64&lt;/a&gt; to translate this gibberish:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MIME::Base64&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( decode_base64 )&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;decode_base64&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;TWVycnkgQ2hyaXN0bWFzIDop&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bingo! He got the code &lt;code&gt;Merry Christmas :)&lt;/code&gt; and elves were able to open the warehouse!&lt;/p&gt;

&lt;h3 id=&#34;Secret-is-compromised&#34;&gt;Secret is compromised!&lt;/h3&gt;

&lt;p&gt;But wait, now everyone is aware of the secret code, including you! This is not acceptable!&lt;/p&gt;

&lt;p&gt;So some senior elves decided to change the code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Env&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;MIME::Base64&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( encode_base64 )&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;encode_base64&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$ENV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;SECRET&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above script is using an environment variable to pass the secret.&lt;/p&gt;

&lt;h3 id=&#34;Make-perl-speak-Spofs-dialect&#34;&gt;Make perl speak Spof&#38;#39;s dialect&lt;/h3&gt;

&lt;p&gt;Aside from maple syrup, Spof enjoys doing some Perl scripting for himself the evening, so after this event he did (or at least he &lt;i&gt;tried&lt;/i&gt;).&lt;/p&gt;

&lt;p&gt;Being still confused he tried to write &lt;code&gt;cHJpbnQgIk1lcnJ5IENocmlzdG1hcyA6KSIK&lt;/code&gt; but it was not working.&lt;/p&gt;

&lt;p&gt;Confused but lazy, he searched the &lt;a href=&#34;https://metacpan.org/&#34;&gt;MetaCPAN&lt;/a&gt; for a solution and went with &lt;a href=&#34;https://metacpan.org/module/Acme::Base64&#34;&gt;Acme::Base64&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Acme::Base64&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;cHJpbnQgIk1lcnJ5IENocmlzdG1hcyA6KSIK&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, the &lt;code&gt;perl&lt;/code&gt; interpreter could understand the &lt;b&gt;base64&lt;/b&gt; dialect spoken by Spof! Magic!&lt;/p&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;You should never feed &lt;a href=&#34;https://en.wikipedia.org/wiki/Gremlins&#34;&gt;Gremlin&lt;/a&gt; after midnight but you also need to monitor closely the maple syrup consumption of elves!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-18T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title>Naughty or Nice Networks</title><link href="http://perladvent.org/2022/2022-12-17.html"/><id>http://perladvent.org/2022/2022-12-17.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;The wise old elf was taking a breather from all the busy preparations and was just looking forward to a richly deserved hot toddy when he heard a familiar knock at the door. He allowed himself the briefest of sighs.&lt;/p&gt;

&lt;p&gt;&#38;quot;Come in, Wispy!&#38;quot;&lt;/p&gt;

&lt;p&gt;In scuttled Wispy Crinkletops wearing a worried expression.&lt;/p&gt;

&lt;p&gt;&#38;quot;You know the wonderful new web portal we set up so that people could write to us directly with their wishes? Well, not all the messages received have been about that. Lots are from people looking to sell us things - and mostly useless things at that! And there are some others which are just so ... rude. How could anyone be so mean?&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Now, now. Don&#38;#39;t get all flustered. You know that this sort of thing is why the boss keeps a Naughty List as well as a Nice List.&#38;quot;. The wise old elf thought for a moment and then asked, &#38;quot;Did you look to see if these all came from the same IP address?&#38;quot;.&lt;/p&gt;

&lt;p&gt;Wispy composed herself and then nodded. &#38;quot;I did check but they were from quite a big number of different addresses so it would take forever to try to deal with them all.&#38;quot;.&lt;/p&gt;

&lt;p&gt;&#38;quot;Hmmm. Can you show me the list?&#38;quot;&lt;/p&gt;

&lt;p&gt;Again Wispy nodded and produced a sizeable sheaf of 11 by 14 fanfold. The wise old elf smiled kindly and ran his eyes down the list. Some definite patterns were detectable and he hit upon an idea.&lt;/p&gt;

&lt;p&gt;&#38;quot;Even though there are a lot of different addresses, it looks like only a dozen or so netblocks are involved. We can use &lt;a href=&#34;https://metacpan.org/module/Net::CIDR::Lite&#34;&gt;Net::CIDR::Lite&lt;/a&gt; to filter those.&#38;quot;. He turned to his terminal and quickly constructed some code. Wispy peered over his shoulder to see.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;CGI::Fast&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Net::CIDR::Lite&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# Build list of netblocks&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$naughty&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Net::CIDR::Lite&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$naughty&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw{10.52.192.0/18 172.26.64.0/20 192.168.188.0/23}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fcgi&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;CGI::Fast&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # Test for presence in the list&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$naughty&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;find&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$ENV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;REMOTE_ADDR&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;triage&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$fcgi&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;warn&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;DEBUG: $ENV{REMOTE_ADDR} is not from a known naughty netblock.\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;process_form&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$fcgi&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;triage&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;	# Push the message onto the moderation queue&lt;br /&gt;&lt;/span&gt;	&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;process_form&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;	# Not from a known naughty netblock, so assume to be nice&lt;br /&gt;&lt;/span&gt;	&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The wise old elf explained, &#38;quot;This allows any number of ranges to be combined into a single list for comparison against the client address. You don&#38;#39;t need to store every single address in the naughty blocks.&#38;quot;&lt;/p&gt;

&lt;p&gt;Wispy was impressed but could see one or two problems. &#38;quot;We don&#38;#39;t use &lt;a href=&#34;https://metacpan.org/module/CGI::Fast&#34;&gt;FCGI&lt;/a&gt; for the web form - it&#38;#39;s all &lt;a href=&#34;https://metacpan.org/module/PSGI&#34;&gt;PSGI&lt;/a&gt; now.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;It&#38;#39;s only an illustration, Wispy - you can use this method with any handler.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;There were IPv6 addresses in the list too. Can we add those?&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;You would need 2 separate objects to hold v4 and v6 addresses but the principle is the same.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;I can never remember the netmasks, though.&#38;quot; moaned Wispy, crestfallen.&lt;/p&gt;

&lt;p&gt;The wise old elf smiled. &#38;quot;You don&#38;#39;t have to use netmasks, just a simple range will do. You can even mix and match, like this:&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;symbol&#34;&gt;$naughty&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_any&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw{10.52.192.0/18 172.26.64.0-172.26.79.255 192.168.188.0/23}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wispy brightened as she could see that this would save time and effort and keep all those naughty girls and boys where they deserved to be. She thanked the wise old elf and headed off to implement the filter, leaving him to enjoy his hot toddy in peace.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-17T00:00:00Z</updated><category term="Perl"/><author><name>Pete Houston</name></author></entry><entry><title>Relocatable Perl</title><link href="http://perladvent.org/2022/2022-12-16.html"/><id>http://perladvent.org/2022/2022-12-16.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;On May 2022, perl v5.36 was &lt;a href=&#34;https://rjbs.cloud/blog/2022/05/perl-5.36/&#34;&gt;released&lt;/a&gt;. Now I always write perl with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  use v5.36;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and I&#38;#39;m very excited to use new features.&lt;/p&gt;

&lt;p&gt;Unfortunately I don&#38;#39;t think too many people use perl v5.36 yet. This is because &lt;i&gt;system&lt;/i&gt; perls are often out-of-date, so people don&#38;#39;t have many chances to use the latest perl.&lt;/p&gt;

&lt;p&gt;It is true that you, an experienced Perl hacker, could build perl v5.36 by yourself. But people who are not very familiar with Perl rarely build perl from source.&lt;/p&gt;

&lt;p&gt;Some programming languages, including &lt;a href=&#34;https://nodejs.org/en/download/&#34;&gt;nodejs&lt;/a&gt; and &lt;a href=&#34;https://go.dev/dl/&#34;&gt;golang&lt;/a&gt;, provide their pre-built binaries. This helps people get started and use the latest version of the languages.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;So what if perl also provides its pre-built binaries?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Because perl itself does not depend on external libraries (except for glibc on linux, etc.), it seems that we can prepare portable perl binaries for each OS/arch. Additionally, since v5.10, perl can be built with &lt;a href=&#34;https://metacpan.org/pod/release/XSAWYERX/perl-5.26.0/pod/perl5100delta.pod#Relocatable-installations&#34;&gt;relocatable INC&lt;/a&gt; so that we can relocate the perl tree wherever we want.&lt;/p&gt;

&lt;p&gt;Well, I prepared pre-built &lt;a href=&#34;https://github.com/skaji/relocatable-perl&#34;&gt;relocatable-perls&lt;/a&gt; for&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;&lt;p&gt;linux amd64&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;linux arm64&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;macOS amd64&lt;/p&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;macOS arm64 (for M1/M2 chips)&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are these useful? Let&#38;#39;s give it a try!&lt;/p&gt;

&lt;h2 id=&#34;Install-relocatable-perls&#34;&gt;Install relocatable-perls&lt;/h2&gt;

&lt;p&gt;There are 3 ways to install relocatable-perls.&lt;/p&gt;

&lt;h3 id=&#34;Manually&#34;&gt;Manually&lt;/h3&gt;

&lt;p&gt;You can manually download tarballs for your OS/arch from &lt;a href=&#34;https://github.com/skaji/relocatable-perl/releases/latest&#34;&gt;release page&lt;/a&gt;. For example, if you use macOS with the M1 chip, then&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  $ curl -fsSL -o perl-darwin-arm64.tar.xz https://github.com/skaji/relocatable-perl/releases/latest/download/perl-darwin-arm64.tar.xz
  $ tar xf perl-darwin-arm64.tar.xz
  $ mv perl-darwin-arm64 ~/wherever-you-want
  $ ~/wherever-you-want/bin/perl -v
  This is perl 5, version 36, subversion 0 (v5.36.0) built for darwin-2level&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;One-liner&#34;&gt;One liner&lt;/h3&gt;

&lt;p&gt;A helper script &lt;a href=&#34;https://github.com/skaji/relocatable-perl/blob/main/perl-install&#34;&gt;perl-install&lt;/a&gt; helps you to install relocatable-perls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  $ curl -fsSL https://raw.githubusercontent.com/skaji/relocatable-perl/main/perl-install | bash -s ~/perl&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This installs the latest relocatable-perl into &lt;code&gt;~/perl&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;plenv&#34;&gt;plenv&lt;/h3&gt;

&lt;p&gt;If you use &lt;a href=&#34;https://github.com/tokuhirom/plenv&#34;&gt;plenv&lt;/a&gt;, then &lt;a href=&#34;https://github.com/skaji/plenv-download&#34;&gt;plenv-download&lt;/a&gt; may be useful:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  $ git clone https://github.com/skaji/plenv-download $(plenv root)/plugins/plenv-download
  $ plenv download latest
  Downloading https://github.com/skaji/relocatable-perl/releases/download/5.36.0.1/perl-darwin-amd64.tar.xz
  Unpacking /Users/skaji/env/plenv/cache/relocatable-5.36.0.1/perl-darwin-amd64.tar.xz
  Successfully installed 5.36.0.1&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;How-to-use-relocatable-perls&#34;&gt;How to use relocatable-perls&lt;/h2&gt;

&lt;p&gt;You can use relocatable-perls just like your usual perls. I have been using relocatable-perls for 8 years and don&#38;#39;t have any particular problems.&lt;/p&gt;

&lt;p&gt;Relocatable-perls come with &lt;a href=&#34;https://metacpan.org/pod/App::cpanminus&#34;&gt;cpanm&lt;/a&gt; so that you are ready to use CPAN modules!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  $ cpanm -nq Plack
  $ plackup -p 8080 -e &#38;#39;sub {[200,[],[&#38;quot;hello world!&#38;quot;]]}&#38;#39;
  HTTP::Server::PSGI: Accepting connections at http://0:8080/&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I think pre-built binaries helps people get started with perl and use the latest version of perl. I prepared &lt;a href=&#34;https://github.com/skaji/relocatable-perl&#34;&gt;relocatable-perls&lt;/a&gt; so that you can give it a try now!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-16T00:00:00Z</updated><category term="Perl"/><author><name>Shoichi Kaji</name></author></entry><entry><title>Create Professional Slideshows with Mojolicious::Plugin::RevealJS</title><link href="http://perladvent.org/2022/2022-12-15.html"/><id>http://perladvent.org/2022/2022-12-15.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h3 id=&#34;Install-and-run-a-Mojolicious-server&#34;&gt;Install and run a Mojolicious server&lt;/h3&gt;

&lt;p&gt;Santa&#38;#39;s elf had a problem. He had to write a presentation very fast and show it to a bunch of new elves. The email assigning this to him was sent by Santa himself. The elf started to look on MetaCPAN and found this module: &lt;a href=&#34;https://metacpan.org/pod/Mojolicious::Plugin::RevealJS&#34;&gt;Mojolicious::Plugin::RevealJS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He quickly typed the following commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cpanm Mojolicius Mojolicious::Plugin::RevealJS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now he could generate a Mojo lite app using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mojo generate lite-app slide_show&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because the elf was trained in the ancient arts of the elders he could open new file with vim and paste this code in:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mojolicious::Lite&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-signatures&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;static&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;paths&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;plugin&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;RevealJS&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;any&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;/&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;template&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;presentation&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;layout&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;revealjs&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then he swiftly created two folders:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    mkdir templates
    mkdir examples&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Use-html-Markdown-to-generate-content&#34;&gt;Use html/Markdown to generate content&lt;/h3&gt;

&lt;p&gt;After that the file for the presentation was generated:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vim templates/presentation.html.ep&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally he could add his first slides to the presentation using html:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;lt;section&#38;gt;
    &#38;lt;h4&#38;gt; Create Professional Slideshows with Mojolicious::Plugin::RevealJS&#38;lt;/h4&#38;gt;
    &#38;lt;p&#38;gt;by Trif Dragos&#38;lt;/p&#38;gt;
    &#38;lt;/section&#38;gt;

    &#38;lt;section&#38;gt;
    &#38;lt;h2&#38;gt;About this talk&#38;lt;/h2&#38;gt;
        &#38;lt;ul&#38;gt;
        &#38;lt;li&#38;gt;Install and run a Mojolicius server&#38;lt;/li&#38;gt;
        &#38;lt;li&#38;gt;Configure Mojolicious::Plugin::RevealJS&#38;lt;/li&#38;gt;
        &#38;lt;li&#38;gt;Use html/MarkDown to generate content&#38;lt;/li&#38;gt;
        &#38;lt;li&#38;gt;Add code snippets in your presentation&#38;lt;/li&#38;gt;
        &#38;lt;li&#38;gt;Add notes visible only for the author of the presentation&#38;lt;/li&#38;gt;
    &#38;lt;/ul&#38;gt;
    &#38;lt;/section&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using the &lt;code&gt;morbo slide_show&lt;/code&gt; command he could start the server. Only after that he was able to access the presentation on his local host: &lt;a href=&#34;http://127.0.0.1:3000&#34;&gt;http://127.0.0.1:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time was ticking. The elf need to speed things up. So, instead of HTML tags, he used Markdown format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    %= markdown_section begin
    #### Create Professional Slideshows with Mojolicious::Plugin::RevealJS
    % end

    %= markdown_section begin
    * Install and run a Mojolicius server
    * Configure Mojolicious::Plugin::RevealJS
    % end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more details on how to do this in Markdown format he used this link: &lt;a href=&#34;https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet&#34;&gt;Markdown-Cheatsheet&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&#34;Add-code-snippets-in-your-presentation&#34;&gt;Add code snippets in your presentation&lt;/h3&gt;

&lt;p&gt;Finally he wanted to insert code snippets in his work. For this he use the &lt;code&gt;include_code&lt;/code&gt; statement which points to the file to include and the correct syntax highlighting to use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;lt;section&#38;gt;
    &#38;lt;section&#38;gt;
        %= include_code &#38;#39;examples/test.pl&#38;#39;,  language =&#38;gt; &#38;#39;perl&#38;#39;
    &#38;lt;/section&#38;gt;
    &#38;lt;section&#38;gt;
        %= include_code &#38;#39;examples/app.js&#38;#39;, language =&#38;gt; &#38;#39;javascript&#38;#39; 
    &#38;lt;/section&#38;gt;
    &#38;lt;/section&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Disaster! The &lt;code&gt;examples/test.pl&lt;/code&gt; file has too much code in it. The new elves will be lost forever if they see this. He opened the file and added some magic comments to it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;lib&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;lib&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;feature&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;say&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# reveal begin object_creation&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$o&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# reveal end object_creation&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$o&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;print_foo_bar&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$o&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$o&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$o&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After the &lt;code&gt;section&lt;/code&gt; key was added to the &lt;code&gt;include_code&lt;/code&gt; statement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;%= include_code &#38;#39;examples/test.pl&#38;#39;, language =&#38;gt; &#38;#39;pl&#38;#39;, section =&#38;gt; &#38;#39;object_creation&#38;#39;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Only this line &lt;code&gt;my $o = Foo-&#38;gt;new();&lt;/code&gt; between those comments was visible in the presentation.&lt;/p&gt;

&lt;h3 id=&#34;Add-notes-visible-only-for-the-author-of-the-presentation&#34;&gt;Add notes visible only for the author of the presentation:&lt;/h3&gt;

&lt;p&gt;Finally he added some notes to each slide:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;lt;section&#38;gt;
    &#38;lt;h4&#38;gt; Create Professional Slideshows with Mojolicious::Plugin::RevealJS&#38;lt;/h4&#38;gt;
    &#38;lt;p&#38;gt;by Trif Dragos&#38;lt;/p&#38;gt;
    %= markdown_section begin
    Note:
    my notes
    %end
    &#38;lt;/section&#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when he pressed &lt;code&gt;s&lt;/code&gt;, he could see the notes from each slide in a new window, which also allowed him to control his presentation.&lt;/p&gt;

&lt;h2 id=&#34;Bibliography&#34;&gt;Bibliography:&lt;/h2&gt;

&lt;dl&gt;

&lt;dt&gt;&lt;a href=&#34;https://www.perl.com/article/94/2014/6/6/Create-professional-slideshows-in-seconds-with-App-revealup/&#34;&gt;Create professional with App revealup&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://www.perl.com/article/134/2014/11/13/Advanced-slideshow-maneuvers/&#34;&gt;Advanced slideshow maneuvers&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;/dl&gt;

&lt;/div&gt;</summary><updated>2022-12-15T00:00:00Z</updated><category term="Perl"/><author><name>drd.trif</name></author></entry><entry><title>Let the Elves Import Your Packages</title><link href="http://perladvent.org/2022/2022-12-14.html"/><id>http://perladvent.org/2022/2022-12-14.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Same as every year, the last few days before Christmas are very busy for the Elves. Those little tinkers are best known for hand-crafting all the presents kids dreamed of, but they also run small but repetitive errands for Santa.&lt;/p&gt;

&lt;p&gt;Did you know he doesn&#38;#39;t need to manually import every single Perl package he has written? Yep, elves do that for him. It&#38;#39;s effortless - he just whispers the namespace and his little helpers take care of the rest.&lt;/p&gt;

&lt;p&gt;At around 2003, Santa managed to spy on the Elves to figure out how they do it. In his infinite generosity, he shared their method with some Perl module authors who later refined it. It was released to the world as &lt;i&gt;EaaPM&lt;/i&gt; (Elves as a Perl Module) named &lt;a href=&#34;https://metacpan.org/module/all&#34;&gt;all&lt;/a&gt;. Fourteen long years have passed since the method was perfected and Santa can still use this module without any issues, thanks to Perl&#38;#39;s excellent backwards compatibility.&lt;/p&gt;

&lt;p&gt;So, what was the method you might ask? Simple. You just had to write &lt;code&gt;use all &#38;#39;NAMESPACE&#38;#39;;&lt;/code&gt; and busy elves would go through your &lt;code&gt;@INC&lt;/code&gt; recursively and import everything they found under that namespace. They had one significant limitation though - no matter how much they practiced, they couldn&#38;#39;t get the hang of importing symbols into the caller. You could tell it just wasn&#38;#39;t their thing.&lt;/p&gt;

&lt;p&gt;How can you benefit from the module? Let&#38;#39;s say you have packages, which are all classes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::Toy&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::ElectronicDevice&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::BoardGame&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::SportsEquipment&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::Candy&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Present::Book&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can just replace all of those lines with one of the following, which will all do the same:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;all&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Present&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;all&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Present::*&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;all&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Present&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&#38;#39;s Straightforward, Stable and Santa-approved - &lt;code&gt;&#38;#39;S&#38;#39; x 3&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Before I go, let me tell you a story of little Timmy.&lt;/p&gt;

&lt;p&gt;Timmy enjoyed programming, especially in Perl. He had his own personal project, on which he spent a lot of his free time. The project grew and grew, and Timmy had implemented self-made tools that would resemble the Elvish method. Little did he know, he had circular imports in his code.&lt;/p&gt;

&lt;p&gt;One day Timmy stumbled upon &lt;a href=&#34;https://metacpan.org/module/all&#34;&gt;all&lt;/a&gt; module while enjoying metacpan. &lt;i&gt;&#38;quot;It&#38;#39;s so old and unmaintained, but I&#38;#39;m going to try it anyway&#38;quot;&lt;/i&gt; he thought while finding and replacing all his in-house code. When his tests all failed, he searched for two hours trying to figure out what was wrong with the module.&lt;/p&gt;

&lt;p&gt;But the module wasn&#38;#39;t broken. Funnily enough, it was his code that was to blame and the module just made it visible. Timmy humbly fixed his architecture and had more confidence in his code ever since. You see, the way Elves work may seem sloppy at first glance, but they actually do their work very well. The moral of the story is: don&#38;#39;t fix something that isn&#38;#39;t broken, especially if actual magic is involved.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-14T00:00:00Z</updated><category term="Perl"/><author><name>Bartosz Jarzyna</name></author></entry><entry><title type="html">Santa&#38;#39;s Helper Embrace the Shell</title><link href="http://perladvent.org/2022/2022-12-13.html"/><id>http://perladvent.org/2022/2022-12-13.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Santa&#38;#39;s workshop is very busy and everyone on staff is expected to contribute beyond just their traditional roles. Even Santa&#38;#39;s reindeer take on additional tasks throughout the year.&lt;/p&gt;

&lt;p&gt;Santa and the elves have been busy this year making vast improvements to their processes, incorporating modern technology such as Perl into their daily workflows.&lt;/p&gt;

&lt;p&gt;To improve their real-time efficiency when it comes to irregular activity, debugging, and general proof-of-concept research, everyone has been working to improve their command line fu. Much of what they do involves working with structured data set, such as JSON files.&lt;/p&gt;

&lt;h3 id=&#34;Typical-reindeer&#34;&gt;Typical reindeer...&lt;/h3&gt;

&lt;p&gt;The reindeer have been helping by extracting important data from the elves&#38;#39; structured notes stored in JSON format. The reindeer need to get the GPS coordinates for the next deliveries in the route.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    {&#38;quot;children&#38;quot;:[{&#38;quot;list&#38;quot;:&#38;quot;naughty&#38;quot;,&#38;quot;name&#38;quot;:&#38;quot;Tom&#38;quot;,&#38;quot;position&#38;quot;:[40.7414728,-74.0055813]},{&#38;quot;location&#38;quot;:[40.7565323,-73.9904037],&#38;quot;name&#38;quot;:&#38;quot;Dick&#38;quot;,&#38;quot;list&#38;quot;:&#38;quot;nice&#38;quot;},{&#38;quot;name&#38;quot;:&#38;quot;Harry&#38;quot;,&#38;quot;list&#38;quot;:&#38;quot;nice&#38;quot;,&#38;quot;location&#38;quot;:[40.7411595,-74.0097167]}]}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reindeer use this data to determine the next deliveries on Santa&#38;#39;s route:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ perl -nE &#38;#39;while (s/&#38;quot;name&#38;quot;:&#38;quot;([^&#38;quot;]+)&#38;quot;,&#38;quot;list&#38;quot;:&#38;quot;nice&#38;quot;,&#38;quot;(position|location)&#38;quot;:\[([^,]+),([^\]]+)//) { say &#38;quot;$1\t$3\t$4&#38;quot; }&#38;#39; &#38;lt; route.json
    Harry   40.7411595      -74.0097167&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The elves confirmed that Tom, who is naughty, did not get added to Santa&#38;#39;s route, but they also noticed that Dick, who is nice, is missing from the list! The reindeers with their poor JSON parser almost caused Dick to get missed! D:&lt;/p&gt;

&lt;p&gt;The elves knew this was not a sustainable approach. They decided that they must adopt better tooling to avoid any tragedies with incorrectly skipping a delivery for a child on Christmas day.&lt;/p&gt;

&lt;h3 id=&#34;The-elves-find-jp&#34;&gt;The elves find &lt;code&gt;jp&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The elves discovered a new command line tool for parsing these JSON files and it allows the use of pointers to drill down to the specific data of interest. This new tool is called &lt;code&gt;jp&lt;/code&gt; -- for JSON Pointer.&lt;/p&gt;

&lt;p&gt;The key features for &lt;code&gt;jp&lt;/code&gt; -- made possible by &lt;a href=&#34;https://docs.mojolicious.org/Mojo/JSON&#34;&gt;Mojo::JSON&lt;/a&gt; from the wonderful &lt;a href=&#34;https://mojolicious.org&#34;&gt;Mojolicious&lt;/a&gt; framework -- are that the elves can use a simple JSON pointer to get at any specific data in their JSON data structure, but then also use Perl data structures to apply logic for ensuring that they extract exactly the right data and not accidentally route Santa to someone on his naughty list.&lt;/p&gt;

&lt;p&gt;The elves first want to look at all of the data in a more natural columnar CSV-type format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ ./jp -r &#38;#39;/children/\d+&#38;#39; /name /list /position /location &#38;lt; advent.json 
    Tom     naughty [40.7414728,-74.0055813]
    Dick    nice    [40.7565323,-73.9904037]
    Harry   nice    [40.7411595,-74.0097167]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now they could easily pipe that to grep to remove the naughty folks, but we can do better better than that, and avoid skipping any nice children whose name contains the word naughty.&lt;/p&gt;

&lt;p&gt;With a little Perl, &lt;code&gt;jp&lt;/code&gt; transforms into a powerful command line tool that Santa and the elves can count on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ ./jp -p -r &#38;#39;/children/\d+&#38;#39; -E &#38;#39;$_-&#38;gt;grep(sub{$_-&#38;gt;jp(&#38;quot;/list&#38;quot;) eq &#38;quot;nice&#38;quot;})&#38;#39; /name /position/0 /location/0 /position/1 /location/1 &#38;lt; advent.json 
    /children/1     Dick    40.7565323      -73.9904037
    /children/2     Harry   40.7411595      -74.0097167&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;jp&lt;/code&gt; is a very new tool and the elves are the first in history to discover its existence. They understand that there may be bugs or additional functionality that it lacks, and they are excited to make contributions to improve &lt;code&gt;jp&lt;/code&gt; and share those improvements with all the children and everyone else in the world. They have confidence in the tool and their ability to make contributions because it is pretty well documented and comes with a very easy to use test suite that already tests most of &lt;code&gt;jp&lt;/code&gt;&#38;#39;s functionality.&lt;/p&gt;

&lt;h4 id=&#34;Download&#34;&gt;Download&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;jp&lt;/code&gt; is available today on &lt;a href=&#34;https://github.com/stefanadams/jp&#34;&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&#34;Usage&#34;&gt;Usage&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;jp&lt;/code&gt; has a detailed help listing, optionally including examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ ./jp -hh
    Usage: ./jp [OPTIONS] [POINTERS]

        Options:
        -A               Dereference JSON arrays into columns
        -C               No collection
        -E eval-string   Evaluate the Perl eval string
                        These functions and variables, in addition to standard Perl functions and variables, are:
            $_            A Mojo::Collection of [JP OBJECTS]
            D             Dump an object to inspect it
            out           Print to stdout and include it in test inspection
            c             Create a new Mojo::Collection object
            f             Create a new Mojo::File object
            l             Create a new Mojo::URL object
            r             Alias to Mojo::Util::dumper
            traverse      Imported from Data::Traverse, if available
        -I exact-match   Compare the results exactly against the supplied text
        -M test-message  Specify a message in the test output
        -R regex         Compare the results against the supplied regex
        -S               Do not sort
        -T eval-string   Compare the results against the supplied Perl eval string
        -U               Remove undef
        -d delimiter     Delimiter to use in columnar output
        -h               Display this help, one more to include examples
        -i               Ignore case in regex JSON pointers
        -k tail-number   Display the bottom n results, n can be negative
        -n head-number   Display the top n results, n can be negative
        -p               Include the pointer in the columnar output
        -r regex-pointer A regex JSON pointer for selecting multiple targets
        -v               Increase verbosity
        
        Jp Objects:
        An object with pointer and value attributes. The primary method to use for this object when iterating a collection
        is the `jp` method which is used to further expand the JSON object by pointer. See the example commented
        &#38;quot;Filtering&#38;quot; for a very practical use case of the Jp object which allows further filtering the results of the regex
        pointer (-r) by iterating the $_ Mojo::Collection of Jp objects with the use of the `grep` method and using a
        JSON Pointer with the `jp` method on each Jp object.

        Pointers:
        Any remaining non-flag arguments are considered JSON pointers and used to narrow the selection from the selected
        JSON string for columnar output.

        Examples:
        (All examples read example.json from stdin, as shown by the first example)

        # Use a JSON pointer to get a value from the JSON data structure
        $ jp /artifactory/0/password &#38;lt; example.json
        s3cr3t

        # Use a JSON pointer to get a value from the JSON data structure, defaults to /
        $ jp
        {&#38;quot;Version&#38;quot;:&#38;quot;1&#38;quot;,&#38;quot;artifactory&#38;quot;:[{...},{...},{...}]}

        # Use a regex in the pointer to reduce the JSON data structure and return each result, one per line
        $ jp -n 1 -r &#38;#39;/artifactory/\d+&#38;#39;
        {...}

        # Use a regex in the pointer to reduce the JSON data structure and include the pointer for all records found
        $ jp -n 1 -p -r &#38;#39;/artifactory/\d+&#38;#39; /user /password
        /artifactory/0  12345 s3cr3t

        # Filtering
        $ jp -Aip -n -1 -d: -E &#38;#39;$_-&#38;gt;grep(sub{$_-&#38;gt;jp(&#38;quot;/isdefault&#38;quot;)})&#38;#39; -r &#38;#39;/Artifactory/\d&#38;#39; /user /password
        /artifactory/1:54321:s3cr3t5

        # Treat the execution as a test
        $ jp -n 1 -E &#38;#39;$_-&#38;gt;tap(sub{out $_-&#38;gt;size})-&#38;gt;tap(sub{out $_-&#38;gt;size})&#38;#39; -r &#38;#39;/artifactory/\d+&#38;#39; /user /password \
            -T &#38;#39;3\n3\n12345\ts3cr3t&#38;#39;
        ok: &#38;#39;Test /user /password&#38;#39; is &#38;#39;3\n3\n12345\ts3cr3t&#38;#39;

        # A syntax error in the -E Perl eval is handled gracefully (final tap method is missing a closing &#38;#39;)&#38;#39;)
        $ jp -v -n 1 -E &#38;#39;$_-&#38;gt;tap(sub{out $_-&#38;gt;size})-&#38;gt;tap(sub{die 123}&#38;#39; -r &#38;#39;/artifactory/\d+&#38;#39; /user /password 
        syntax error in -E eval

        # Don&#38;#39;t sort by pointer, sort arbitrarily as specified in the -E Perl eval
        $ jp -v -S -U -p -r &#38;#39;/markers/\d&#38;#39; -E &#38;#39;$_-&#38;gt;sort(sub{$a-&#38;gt;jp(&#38;quot;/location/0&#38;quot;, &#38;quot;/position/0&#38;quot;) &#38;lt;=&#38;gt; $b-&#38;gt;jp(&#38;quot;/location/0&#38;quot;, &#38;quot;/position/0&#38;quot;)})&#38;#39; /location /position &#38;lt;&#38;lt;EOF
        {&#38;quot;markers&#38;quot;:[{&#38;quot;name&#38;quot;:&#38;quot;Google, 8th Avenue&#38;quot;,&#38;quot;position&#38;quot;:[40.7414728,-74.0055813]},{&#38;quot;name&#38;quot;:&#38;quot;Microsoft, Times Square&#38;quot;,&#38;quot;location&#38;quot;:[40.7565323,-73.9904037]},{&#38;quot;name&#38;quot;:&#38;quot;Tesla, Washington Street&#38;quot;,&#38;quot;location&#38;quot;:[40.7411595,-74.0097167]},{&#38;quot;name&#38;quot;:&#38;quot;Amazon New York&#38;quot;,&#38;quot;location&#38;quot;:[40.7532822,-74.0010696]}]}
        EOF&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;</summary><updated>2022-12-13T00:00:00Z</updated><category term="Perl"/><author><name>Stefan Adams</name></author></entry><entry><title>The Delivery Map</title><link href="http://perladvent.org/2022/2022-12-12.html"/><id>http://perladvent.org/2022/2022-12-12.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Santa has started to get more absent-minded lately. Year after year he tends to forget a few more things. Just little things like where he left the keys to the sled, or to put his red Santa hat on before he leaves the house.&lt;/p&gt;

&lt;p&gt;To give you an idea, in 2021, Santa completely forgot to deliver presents to the Johnson family in Birmingham. He had to come back later to fix it, and nearly got caught by the children!&lt;/p&gt;

&lt;p&gt;This kind of mistake takes time and is tiring for Santa. His right-hand elf, worried about Santa&#38;#39;s well being, just came up with a solution.&lt;/p&gt;

&lt;p&gt;He started to design &#38;quot;TODO-Maps&#38;quot; for his boss.&lt;/p&gt;

&lt;p&gt;For this purpose, he decided to use the &lt;a href=&#34;https://metacpan.org/module/GraphViz2&#34;&gt;GraphViz2&lt;/a&gt; Perl module, to build a graph of families to deliver to.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://graphviz.org/&#34;&gt;GraphViz&lt;/a&gt; is a well known graph visualization software and is easy to use, and the elf was able to come up with a first graph in a matter of minutes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;rankdir&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;LR&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Anderson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Williams&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;simple.svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And got this nice result:&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;simple.svg&#34; alt=&#34;A simple delivery map&#34;&gt;&lt;/center&gt;

&lt;h3 id=&#34;Make-it-a-Bit-Better&#34;&gt;Make it a Bit Better&lt;/h3&gt;

&lt;p&gt;It was already a nice help for Santa, but the elf wanted to make it a bit better.&lt;/p&gt;

&lt;p&gt;First, to materialize the direction using &lt;code&gt;directed =&#38;gt; 1&lt;/code&gt;, and second, to change the node shape to house using &lt;code&gt;shape =&#38;gt; &#38;quot;house&#38;quot;&lt;/code&gt; because after all, these families live in houses!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Birmingham&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;directed&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;graph&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;rankdir&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;LR&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;default_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;shape&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;house&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;width&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;2&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;2&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Anderson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Williams&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;better.svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And got this result:&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;better.svg&#34; alt=&#34;A better delivery map&#34;&gt;&lt;/center&gt;

&lt;h3 id=&#34;The-Full-Procedure-for-Santa&#34;&gt;The Full Procedure for Santa&lt;/h3&gt;

&lt;p&gt;Santa was already happy with this map but wanted to go even a bit further.&lt;/p&gt;

&lt;p&gt;If the map could also display the chores he would do to get ready for the day, it would be perfect for Santa!&lt;/p&gt;

&lt;p&gt;To give you a better idea, this is what Santa&#38;#39;s typical day looked like: he would leave his home, head to the shop for some chocolate bars to sustain him on his travels, then walk over to the sled&#38;#39;s garage and then finally start his tour (can be a delivery tour if it&#38;#39;s Christmas day, or it can be visiting toy crafters to discover new products).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;GraphViz2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Birmingham&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;directed&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;graph&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;rankdir&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;LR&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;default_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;shape&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;house&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;width&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;2&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;2&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;push_subgraph&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;cluster_NorthPole&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;North Pole&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Santa&#39;s house&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Supermarket&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Sleds&#39; garage&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pop_subgraph&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;push_subgraph&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;cluster_Birmingham&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;graph&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Birmingham&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Anderson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_node&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Williams&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pop_subgraph&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Santa&#39;s house&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Supermarket&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Supermarket&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Sleds&#39; garage&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Sleds&#39; garage&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Anderson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Anderson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Johnson&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add_edge&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Taylor&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Williams&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$graph&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;final.svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It resulted in this graph:&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;final.svg&#34; alt=&#34;Final delivery map&#34; width=&#39;1200&#39;&gt;&lt;/center&gt;

&lt;p&gt;Elves started to print these kinds of maps for every tour Santa has to do, and Christmas was once again a success!&lt;/p&gt;

&lt;p&gt;More &lt;a href=&#34;https://graphviz-perl.github.io/&#34;&gt;examples&lt;/a&gt; of &lt;a href=&#34;https://metacpan.org/module/GraphViz2&#34;&gt;GraphViz2&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-12T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title>Wake up! Time to open presents! </title><link href="http://perladvent.org/2022/2022-12-11.html"/><id>http://perladvent.org/2022/2022-12-11.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Wake-up-Time-to-open-presents&#34;&gt;Wake up! Time to open presents!&lt;/h2&gt;

&lt;p&gt;Clark W. Grisman faced a dilemma, it was the night before Christmas; and he found himself up against a programming deadline. Why a company at the cutting edge of milk-proof cereal coatings required him to write a Perl program, Clark can&#38;#39;t remember, but he does know that he&#38;#39;s trying to read from a socket that keeps timing out!&lt;/p&gt;

&lt;h2 id=&#34;Traditional-alarm-Handling&#34;&gt;Traditional &lt;code&gt;alarm&lt;/code&gt; Handling&lt;/h2&gt;

&lt;p&gt;In the past, whenever Clark wanted to call a procedure inside his Perl code that might take too long to return, he always simply copied the example in &lt;code&gt;perldoc -f alarm&lt;/code&gt;, which at the time of this Advent season looks like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;eval&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$SIG&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;ALRM&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;alarm\n&#38;quot;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# NB: \n required&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;alarm&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$timeout&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$nread&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sysread&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$socket&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$buffer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$size&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;alarm&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$@&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;$@&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;eq&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;alarm\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# propagate unexpected errors&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # timed out&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # didn&#39;t&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If he didn&#38;#39;t need it quite so fancy, he&#38;#39;d just nip it down to:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;symbol&#34;&gt;$SIG&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;ALRM&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;alarm\n&#38;quot;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;};&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# NB: \n required&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;alarm&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$timeout&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$nread&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sysread&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$socket&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$buffer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$size&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;alarm&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Clark never liked using &lt;code&gt;alarm&lt;/code&gt; in this latter way because it didn&#38;#39;t feel very &lt;i&gt;perlish&lt;/i&gt;. But he did what he had to, then would just bottle up the guilt. That&#38;#39;s what the eggnog is for, he&#38;#39;d tell himself.&lt;/p&gt;

&lt;h2 id=&#34;alarm-Handling-Comes-to-Christmastown&#34;&gt;&lt;code&gt;alarm&lt;/code&gt; Handling Comes to Christmastown&lt;/h2&gt;

&lt;p&gt;Clark is not only a food scientist by day, but he considers himself a Perl artist by night. Realizing this approach seemed a little dated, he recalled seeing a module fly by the CPAN radar that treats &lt;code&gt;alarm&lt;/code&gt;&#38;#39;s &lt;code&gt;ALRM&lt;/code&gt; signal as a catchable exception.&lt;/p&gt;

&lt;p&gt;After some searching, he found the module. &lt;a href=&#34;https://metacpan.org/module/Try::ALRM&#34;&gt;Try::ALRM&lt;/a&gt;. Turns out there was no need to fiddle with the &lt;code&gt;eval&lt;/code&gt; stuff directly. Using this handy module, it can be done in the following way using a multi-level block that looks a lot a &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;catch&lt;/code&gt; construct.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Try::ALRM&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;# thing that can time out&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;try_once&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$nread&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sysread&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$socket&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$buffer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$size&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# code block locally assigned to $SIG{ALRM}&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;ALRM&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;warn&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{Wake up! `sysread` has timed out!}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# code run after $SIG{ALRM}&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;finally&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # timed out&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # didn&#39;t&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# trailing modifier to set timeout (in seconds)&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;timeout&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$timeout&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cleaned up, Clark&#38;#39;s code came out to be:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;try_once&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$nread&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sysread&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$socket&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$buffer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$size&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# NB: no ALRM block is a localized no-op $SIG{ALRM}!&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;finally&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # timed out&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # didn&#39;t&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;timeout&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$timeout&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the above code, Clark found he didn&#38;#39;t even need to define the &lt;code&gt;ALRM&lt;/code&gt; handler block, so he didn&#38;#39;t include it. Effectively the &lt;code&gt;$SIG{ALRM}&lt;/code&gt; handler was a &lt;i&gt;no-op&lt;/i&gt;.&lt;/p&gt;

&lt;h2 id=&#34;retry:-Never-Gonna-Give-It-Up&#34;&gt;&lt;code&gt;retry&lt;/code&gt;: &lt;i&gt;Never Gonna Give It Up&lt;/i&gt; ...&lt;/h2&gt;

&lt;p&gt;.. not immediately, anyway.&lt;/p&gt;

&lt;p&gt;Clark was not satisfied, since he wanted to add some retries; and this is when &lt;a href=&#34;https://metacpan.org/module/Try::ALRM&#34;&gt;Try::ALRM&lt;/a&gt; &lt;i&gt;really&lt;/i&gt; proved its worth. And Clark really needed a win. Chicago PD just &lt;i&gt;SWAT&lt;/i&gt;&#38;#39;d the Grisman home because in a misguided attempt at some Christmas cheer, cousin Eddie had, among other things, just emptied the entire contents of his RV&#38;#39;s septic tank into the neighborhood&#38;#39;s drainage system.&lt;/p&gt;

&lt;p&gt;In all its full glory, Clark finished his code in time to enjoy a lot of spiked eggnog before getting some sleep.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Try::ALRM&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# ...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;retry&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total_tries&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;tries&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{Attempt #%d of %d ...\n}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total_tries&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$nread&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sysread&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$socket&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$buffer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$size&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;ALRM&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;shift&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total_tries&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;tries&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$msg&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;sprintf&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{FAILED: Attempt #%d of %d ...\n}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$total_tries&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;warn&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$msg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;finally&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$attempt&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$successful&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # timed out&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;        # didn&#39;t&lt;br /&gt;&lt;/span&gt;    &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;timeout&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$timeout&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;tries&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;It-Was-Just-A-Dream&#34;&gt;It Was Just A Dream&lt;/h2&gt;

&lt;p&gt;... or was it! Clark frantically searched the house for evidence of the shenanigans of the night before, but realized that it was all a dream. Good thing, because he was really starting to get a hankerin&#38;#39; for the pickle jelly from the Jelly of the Month Club.&lt;/p&gt;

&lt;p&gt;Clark did realize that he wished for one part of that dream to be true. Something like this &lt;a href=&#34;https://metacpan.org/module/Try::ALRM&#34;&gt;Try::ALRM&lt;/a&gt; sure would be a blessing for a lot of things! And what to his wondering eyes did appear, after searching on &lt;i&gt;MetaCPAN&lt;/i&gt;, was &lt;a href=&#34;https://metacpan.org/module/Try::ALRM&#34;&gt;Try::ALRM&lt;/a&gt; and 8 tiny reindeer!&lt;/p&gt;

&lt;p&gt;And just at that moment, he&#38;#39;s convinced he heard Santa&#38;#39;s bells and a jolly old, &lt;i&gt;Ho, Ho, Ho! Merrry Christmas!&lt;/i&gt;. He also now sees 8 tiny reindeer everywhere and is really worried that Uncle Eddie slipped more than bottom shelf Kentucky Bourbon in that eggnog.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-11T00:00:00Z</updated><category term="Perl"/><author><name>oodler</name></author></entry><entry><title>The Christmas Time Machine</title><link href="http://perladvent.org/2022/2022-12-10.html"/><id>http://perladvent.org/2022/2022-12-10.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h3 id=&#34;A-Terrible-Flashback&#34;&gt;A Terrible Flashback&lt;/h3&gt;

&lt;p&gt;At the North Pole, the elves are just starting the Christmas 2022 preparations.&lt;/p&gt;

&lt;p&gt;As usual they restarted doing line work, building toys, then sorting them per area. Everyone happily singing and working! When suddenly one elf put the first toy in a box marked &#38;quot;Salt Lake City&#38;quot; and was surprised it was not empty...&lt;/p&gt;

&lt;p&gt;And he had a terrible flashback, they seemed to have forgotten to deliver the 2021 toys to Salt Lake City!&lt;/p&gt;

&lt;h3 id=&#34;Go-Ask-Santa&#34;&gt;Go Ask Santa&lt;/h3&gt;

&lt;p&gt;The elves panicked, so they quickly reached out to Santa for a solution.&lt;/p&gt;

&lt;p&gt;He took some time to think about it, then had an idea: Let&#38;#39;s use the time machine to go back to 2021 and deliver the gifts!&lt;/p&gt;

&lt;p&gt;(If you&#38;#39;re wondering: YES, time machines do exist in North Pole! And I bet that elves even already used it in the past for similar mistakes? :P)&lt;/p&gt;

&lt;p&gt;So a group of elves decided to use the time machine, fixed the arrival date to 25 December 2021, pushed the &#38;quot;go&#38;quot; button and zooooooooooooop!&lt;/p&gt;

&lt;h3 id=&#34;Try-to-Deliver-Back-in-the-Past&#34;&gt;Try to Deliver Back in the Past&lt;/h3&gt;

&lt;p&gt;Upon arriving in 2021, they immediately tried to run Perl software that they took with them.&lt;/p&gt;

&lt;p&gt;For the record, in 2021, North Pole was equipped with Ubuntu 20.04 and here is the Perl code they had:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;feature&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;try&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;no&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;experimental::try&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;deliver&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Failed to deliver\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But it failed with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    Feature &#38;quot;try&#38;quot; is not supported by Perl 5.30.0 at deliver.pl line 3.
    BEGIN failed--compilation aborted at deliver.pl line 3.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is because the &lt;code&gt;perl&lt;/code&gt; interpreter on which they wanted to run the code is older (5.30 in Ubuntu 20.04) than the one from where they are coming (5.36 in a rolling release distribution).&lt;/p&gt;

&lt;p&gt;This is called &#38;quot;forward compatibility&#38;quot;.&lt;/p&gt;

&lt;h3 id=&#34;The-Perl-Time-Machine&#34;&gt;The Perl Time Machine&lt;/h3&gt;

&lt;p&gt;One of the elves had heard about the Perl &#38;quot;Time Machine&#38;quot; and was finally able to fix the Perl script thanks to &lt;a href=&#34;https://metacpan.org/module/Feature::Compat::Try&#34;&gt;Feature::Compat::Try&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/perl&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Feature::Compat::Try&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;deliver&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$e&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Failed to deliver\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, the CPAN module enables the feature &lt;code&gt;try&lt;/code&gt; for capable interpreters or implements the feature &lt;code&gt;try&lt;/code&gt; for older ones. It allowed the &lt;code&gt;try&lt;/code&gt; feature to &#38;quot;travel&#38;quot; in the past with the elves and it also means that, back in 2022, elves would be able to reuse the updated version of the script without any change.&lt;/p&gt;

&lt;p&gt;Thanks to this trick, the 2021 Christmas of Salt Lake City was saved! Ouf!&lt;/p&gt;

&lt;p&gt;Credits to Paul Evans for &lt;a href=&#34;https://metacpan.org/module/Feature::Compat::Try&#34;&gt;Feature::Compat::Try&lt;/a&gt; and &lt;a href=&#34;https://youtu.be/Kc_bP73xNyM&#34;&gt;Perl&#38;#39;s Amazing Time Machine&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-10T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title>What did Santa forget?</title><link href="http://perladvent.org/2022/2022-12-09.html"/><id>http://perladvent.org/2022/2022-12-09.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Santa is about ready to start his yearly trip around the world! But does he &lt;i&gt;really&lt;/i&gt; have everything?&lt;/p&gt;

&lt;p&gt;It would be silly not to deliver a present to someone who has been trying the whole year to be nice. Luckily, to avoid such a blunder, he made a list beforehand:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%santas_list&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;presents&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Rob&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Lisa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Brian&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Amy&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Chris&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Larry&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Scott&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Sabina&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Shirley&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Richard&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Amy&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;other&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;candy canes&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;fireplace break-in tool&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;cookies degustation kit&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all he needs to do is compare it to the list of things he packed. He asked the elves how should he do it, and they suggested giving a try to recently released module &lt;a href=&#34;https://metacpan.org/module/Value::Diff&#34;&gt;Value::Diff&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%santas_package&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;presents&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Richard&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Rob&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Lisa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Larry&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Brian&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Scott&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Sabina&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Shirley&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Amy&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;for Chris&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;other&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;cookies degustation kit&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;candy canes&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;sleigh repair tool&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;single&#34;&gt;&#39;fireplace break-in tool&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.36&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Value::Diff&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Data::Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;diff&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%santas_list&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%santas_package&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$missing&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;looks like you forgot something: &#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$missing&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;all looks good...&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;diff&lt;/code&gt; function used here recursively compares its two first arguments, creating a new data structure which contains the differences. It returns a true value if the arguments are not equal, and the diff is put into &lt;code&gt;$missing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this program, Santa got his answer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    looks like you forgot something: $VAR1 = {
              &#38;#39;presents&#38;#39; =&#38;gt; [
                              &#38;#39;for Amy&#38;#39;
                            ]
            };&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Right! There are two Amys on the list, and he only has a present for one. Of course he doesn&#38;#39;t need last names, he simply distinguishes them by their first names alone.&lt;/p&gt;

&lt;p&gt;Rudolph liked the new module, but since he&#38;#39;s a reindeer he has major difficulties typing on the keyboard. He read the documentation thoroughly instead and noticed that the module only finds missing elements, not the excessive ones! So Santa reversed the order of values and tried again:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;diff&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%santas_package&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%santas_list&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$excess&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;looks like you have something extra: &#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Dumper&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$excess&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;all looks very good now...&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;diff&lt;/code&gt; function tries to find a Perl data structure which describes the patch for the second value to be equal to the first one. With arguments order reversed in the second call, Santa could see the full picture:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    looks like you forgot something: $VAR1 = {
              &#38;#39;presents&#38;#39; =&#38;gt; [
                              &#38;#39;for Amy&#38;#39;
                            ]
            };
    looks like you have something extra: $VAR1 = {
              &#38;#39;other&#38;#39; =&#38;gt; [
                           &#38;#39;sleigh repair tool&#38;#39;
                         ]
            };&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well of course he doesn&#38;#39;t need that, he can use magic instead!&lt;/p&gt;

&lt;p&gt;It was getting late and the fireplace started to flicker out. Happy with his program, Santa put his laptop away, stood up and picked up his presents bag. Ho Ho Ho, it&#38;#39;s time for the delivery!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-09T00:00:00Z</updated><category term="Perl"/><author><name>Bartosz Jarzyna</name></author></entry><entry><title>A Perlmas Tree</title><link href="http://perladvent.org/2022/2022-12-08.html"/><id>http://perladvent.org/2022/2022-12-08.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h3 id=&#34;How-to-Buy-a-Christmas-Tree-on-Christmas-Day-:-S&#34;&gt;How to Buy a Christmas Tree on Christmas Day :-S&lt;/h3&gt;

&lt;p&gt;It&#38;#39;s just before Christmas Eve. The air smells of cinnamon and gingerbread, the most beautiful Christmas melodies sound everywhere, the Christmas goose has already been ordered, but wait... A very important detail is missing. Rudolph, the Christmas grouch, did not buy a Christmas tree! And so his wife Fjolla, a Christmas elf, asks him to finally get a tree. The same procedure as every year...&lt;/p&gt;

&lt;p&gt;But it&#38;#39;s just before Christmas Eve... And so the Christmas tree stand of Knecht Ruprecht is sold out.&lt;/p&gt;

&lt;h3 id=&#34;A-Do-it-Yourself-Tree-with-perl&#34;&gt;A Do-it-Yourself Tree with perl&lt;/h3&gt;

&lt;p&gt;&#38;quot;No problem&#38;quot;, Rudolph thinks. Nowadays you can create a Christmas tree with perl. There was a wonderful module by Dave Cross in the &lt;a href=&#34;https://www.perladvent.org/2018/2018-12-12.html&#34;&gt;Perl Advent Calendar 2018&lt;/a&gt;. But to find the perfect fitting tree, you have to hack the code. Therefore a GUI is needed. And why not to try the new module &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt; is an object oriented binding to the &lt;a href=&#34;https://www.enlightenment.org/about-efl&#34;&gt;Enlightenment Foundation Libraries&lt;/a&gt;. And even if it is a very young module, the Elementary part (the widget toolkit) is already very usable. But let&#38;#39;s see:&lt;/p&gt;

&lt;p&gt;But before take a deep dive into &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt; we make a global hash for the settings to &lt;a href=&#34;https://metacpan.org/module/SVG::ChristmasTree&#34;&gt;SVG::ChristmasTree&lt;/a&gt; with nice defaults on top of our code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%settings&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;layers&lt;/span&gt;        &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;width&lt;/span&gt;         &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;trunk_length&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;pot_height&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;leaf_colour&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rgb(9,186,10)&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;bauble_colour&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rgb(212,175,55)&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;trunk_colour&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rgb(139,69,19)&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;pot_colour&lt;/span&gt;    &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rgb(133,100,69)&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All &lt;a href=&#34;https://metacpan.org/module/pEFL::Elm&#34;&gt;pEFL::Elm&lt;/a&gt; applications share the following basic framework, which initializes Elementary, runs the Mainloop and do cleanup when the program exists:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SVG::ChristmasTree&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# for creating the Christmas tree&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Evas&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# for EVAS_CONSTANTS_&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pEFL::Elm::init&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;arrayindex&#34;&gt;$#ARGV&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;@ARGV&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pEFL::Elm::policy_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;ELM_POLICY_QUIT&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;ELM_POLICY_QUIT_LAST_WINDOW_CLOSED&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;### (...GUI CODE COMES HERE...)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pEFL::Elm::run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;pEFL::Elm::shutdown&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Perhaps a little explanation to the policies set with &lt;code&gt;pEFL::Elm::policy_set()&lt;/code&gt;: this causes the Mainloop started by &lt;code&gt;pEFL::Elm::run()&lt;/code&gt; to quit automatically when the last window of the application is closed.&lt;/p&gt;

&lt;p&gt;To create a standard window with a standard background we use the special constructor &lt;code&gt;pEFL::Elm::Win-&#38;gt;util_standard_add($name, $title)&lt;/code&gt;. The autodel setting means that if someone hits the close button, or otherwise uses some normal environment mechanism (keybinding, menu) to close the window, the window object is automatically deleted on the application side. If you don&#38;#39;t do this, these mechanisms will not work and the window will stay around if you do not manually add a callback to handle &#38;quot;delete, request&#38;quot; events.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Win&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;util_standard_add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;christmas-tree&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Christmas Tree&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;autodel_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;resize&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The content will be framed in a &lt;a href=&#34;https://metacpan.org/module/pEFL::Elm::Box&#34;&gt;pEFL::Elm::Box&lt;/a&gt;. This basic container of Elementary is just a linear method of arranging widgets horizontally or vertically. Attention should be paid to the functions &lt;code&gt;$widget-&#38;gt;size_hint_weight|align_set(x_expand|align, y_expand_align)&lt;/code&gt;. With these you control hints for expanding and aligning of the widget packed to the container box. Possible arguments are 0.0 (no expand/align to left/top) to 1.0 (expand/align to the right/bottom). If you want the widget to take up all the space in its parent you can use the special constants &lt;code&gt;EVAS_HINT_EXPAND&lt;/code&gt; and &lt;code&gt;EVAS_HINT_FILL&lt;/code&gt; together. Because it is much paperwork, we create a function for widgets that expand and fill in all directions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Frame&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_expand_widget&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Box&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_expand_widget&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;style_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;pad_large&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;content_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;resize_object_add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$frame&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;_expand_widget&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$widget&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$widget&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_weight_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_EXPAND&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_EXPAND&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$widget&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_align_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_FILL&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_FILL&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the container box we pack three widgets:&lt;/p&gt;

&lt;dl&gt;

&lt;dt&gt;1. An pEFL::Elm::Image widget that serves as a viewer&lt;/dt&gt;
&lt;dd&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Image&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_expand_widget&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pack_end&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/dd&gt;
&lt;dt&gt;2. An pEFL::Elm::Table widget where the controls of the several settings are aligned&lt;/dt&gt;
&lt;dd&gt;

&lt;p&gt;A table is like a box with 2 dimensions. An item of the table can span multiple columns and rows, and even overlap with other items.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;padding_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_weight_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_EXPAND&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# Expand and fill only to the&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_align_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_FILL&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;      &lt;span class=&#34;comment&#34;&gt;# X-Direction&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pack_end&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For changing the settings of the tree we add several sliders.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;_add_slider_setting&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Width of the tree&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;min&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;700&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;max&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;3000&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;width&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_add_slider_setting&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Layers&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;min&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;max&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;layers&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_add_slider_setting&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Trunk length&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;min&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;max&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;trunk_length&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;_add_slider_setting&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Pot height&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;min&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;max&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;pot_height&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For this we use the custom function &lt;code&gt;_add_slider_settings($table,$row,$option_hash)&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;_add_slider_setting&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$label&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Label&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$label&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;text_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$label&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pack&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$label&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Slider&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_align_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_FILL&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;size_hint_weight_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;EVAS_HINT_EXPAND&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;min_max_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;step_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;indicator_format_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;%1.0f&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;value_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$settings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}});&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$table&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pack&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$spinner&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;smart_callback_add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;delay,changed&#38;quot;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$settings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$opts&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;value_get&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;());}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;core&#34;&gt;undef&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Most of the code should be self-explanatory. Therefore only two little explanations:&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;$spinner-&#38;gt;indicator_format_set(&#38;quot;%1.0f&#38;quot;);&lt;/code&gt; the popup for the actual value shows only integers.&lt;/p&gt;

&lt;p&gt;Very important is the &lt;code&gt;$spinner-&#38;gt;smart_callback_add(&#38;quot;eventName&#38;quot;,\&#38;amp;eventSub,$data)&lt;/code&gt;. With this you can register an event handler for smart callbacks, the most often used event types in EFL. The callback function takes as parameters the additional &lt;code&gt;$data&lt;/code&gt; defined in the &lt;code&gt;$widget-&#38;gt;smart_callback_add()&lt;/code&gt;, the object to which the event happened, and the event info data, which depends on the object type and the event at play. So the signature is&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;smart_event_cb&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$data&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$obj&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$evInfo&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the example code we use an anonymous subroutine as event handler that sets the key in the setting hash with the actual value of the spinner object.&lt;/p&gt;

&lt;/dd&gt;
&lt;dt&gt;3. Last we add the button to create the Christmas tree to the container-box&lt;/dt&gt;
&lt;dd&gt;

&lt;p&gt;and show the window (don&#38;#39;t forget this!!)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$btn&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;pEFL::Elm::Button&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$btn&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;text_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;Create a new Christmas Tree&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$btn&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;smart_callback_add&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;clicked&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;&#38;amp;create_christmas_tree&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$btn&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$container&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;pack_end&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$btn&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$win&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again we register a callback to the following event handler that creates the SVG file and let the viewer show the created tree. A little hack is needed with &lt;code&gt;$viewer-&#38;gt;file_set(undef,&#38;quot;&#38;quot;)&lt;/code&gt;. Otherwise the viewer doesn&#38;#39;t know that the file has changed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;create_christmas_tree&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$obj&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$evinfo&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;magic&#34;&gt;@_&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$tree&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;SVG::ChristmasTree&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;%settings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;gt;&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;tree.svg&#38;quot;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;die&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Could not write to ./tree.svg: $!\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$tree&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;as_xml&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;close&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$fh&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;file_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;core&#34;&gt;undef&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$viewer&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;file_set&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;./tree.svg&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;double&#34;&gt;&#38;quot;&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed this little introduction to &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt;. Because the Perl advent articles should be light and trivial, the explained version only gives you control over the numeric settings of &lt;a href=&#34;https://metacpan.org/module/SVG::ChristmasTree&#34;&gt;SVG::ChristmasTree&lt;/a&gt;. But at &lt;a href=&#34;https://github.com/MaxPerl/PerlAdvent2022&#34;&gt;my Perl Advent 2022 github repository&lt;/a&gt; you find also an advanced version where you can also alter the colors of the tree, baubles and pot. The additions adjust the colorselector examples under &lt;code&gt;examples/colorselector.pl&lt;/code&gt; in the &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt; distribution and hopefully are understandable.&lt;/p&gt;

&lt;p&gt;If you want to get deep into programming with &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt;, see the explanations at &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt;. As the API of &lt;a href=&#34;https://metacpan.org/module/pEFL&#34;&gt;pEFL&lt;/a&gt; is (apart from its object-oriented interface) deliberately kept close to the Elementary C API, the documentations at the &lt;a href=&#34;https://www.enlightenment.org/develop/legacy/api/c/start#&#34;&gt;Enlightenment docs&lt;/a&gt; should help you, too. The Perl method names usually remove the prefix at the beginning of the C functions. Therefore applying the C documentation should be no problem.&lt;/p&gt;

&lt;p&gt;And of course, you can get help at &lt;a href=&#34;https://github.com/MaxPerl/Perl-Efl&#34;&gt;Github&lt;/a&gt;. And perhaps you want to contribute and to make the pEFL bindings better? In any case there is much to do :-)&lt;/p&gt;

&lt;p&gt;Merry Christmas &#38;#x1F384; &#38;#x1F384; &#38;#x1F384; &#38;#x1F384; &#38;#x1F384; &#38;#x1F384;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-08T00:00:00Z</updated><category term="Perl"/><author><name>Maximilian Lika</name></author></entry><entry><title>The Sleigh odometer</title><link href="http://perladvent.org/2022/2022-12-07.html"/><id>http://perladvent.org/2022/2022-12-07.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h2 id=&#34;Sleigh-Odometer&#34;&gt;Sleigh Odometer&lt;/h2&gt;

&lt;h3 id=&#34;Customize-the-Sleigh&#34;&gt;Customize the Sleigh&lt;/h3&gt;

&lt;p&gt;It&#38;#39;s already December and elves are working hard to produce all of the toys for Christmas.&lt;/p&gt;

&lt;p&gt;On the other side, Santa is preparing his sleigh, cleaning or customizing.&lt;/p&gt;

&lt;p&gt;This year, in addition to a temperature sensor, Santa asked to install an odometer to his sleigh so that he can count each delivery. For the record, the distance unit is neither kilometers nor miles nor inches but &#38;quot;elf little toe&#38;quot;... but it does not change what follows :)&lt;/p&gt;

&lt;p&gt;In order to implement the counter of the odometer, an elf came up with this code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;5.010&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;prototype&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But sadly it does not work as expected because the distance is reset at each &lt;code&gt;count()&lt;/code&gt; call :/&lt;/p&gt;

&lt;h3 id=&#34;Asking-Experienced-Elves&#34;&gt;Asking Experienced Elves&lt;/h3&gt;

&lt;p&gt;After asking some more experienced elves, the elf decided to implement a persistent variable via a &#38;quot;lexical trick&#38;quot;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;5.010&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it worked!&lt;/p&gt;

&lt;p&gt;Some other experienced elf proposed to use a &#38;quot;closure&#38;quot; that he perceived as &#38;quot;more elegant&#38;quot;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;5.010&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;make_counter&lt;/span&gt;&lt;span class=&#34;prototype&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;make_counter&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$counter&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Final-Word-from-Santa&#34;&gt;Final Word from Santa&lt;/h3&gt;

&lt;p&gt;These 2 previous pieces of code work well, but there is definitely a simpler way!&lt;/p&gt;

&lt;p&gt;As usual, the final word came from Santa who decided to use &lt;a href=&#34;https://perldoc.perl.org/functions/state&#34;&gt;state&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;#!/usr/bin/env perl&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;5.010&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;prototype&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$distance&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;say&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this new &#38;quot;option&#38;quot;, Santa felt upgraded and was able to know when to take a break or when to feed the reindeers!&lt;/p&gt;

&lt;p&gt;And most important of all, it helped to arrive on time for the dinner prepared by Mrs Claus!&lt;/p&gt;

&lt;h3 id=&#34;References&#34;&gt;References&lt;/h3&gt;

&lt;p&gt;See &lt;a href=&#34;https://perlmaven.com/static-and-state-variables-in-perl&#34;&gt;Perl Maven &#38;quot;static and state variables in perl&#38;quot;&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-07T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title type="html">St. Nick&#38;#39;s Reindeers Need H2O!</title><link href="http://perladvent.org/2022/2022-12-06.html"/><id>http://perladvent.org/2022/2022-12-06.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Reindeer are generally hardy creatures, but the ones Santa chooses must also be of the &lt;i&gt;heartiest&lt;/i&gt; character. Though they spend only 24 hours of the whole year &lt;i&gt;in flight&lt;/i&gt;, it is during this marathon that they must cheerfully give all they have. And Santa makes sure that they have all the hydration and other essentials their bodies need. Recently St. Nick&#38;#39;s head reindeer trainer has purchased a new set of &lt;i&gt;Camelbak&lt;/i&gt; personal H2O delivery systems that is highly tuned for use &lt;i&gt;in flight&lt;/i&gt;, which have 3 reservoirs rather than the standard 1, so that they don&#38;#39;t get too parched.&lt;/p&gt;

&lt;p&gt;Being one who obviously dabbles in Perl in the off season, Santa was reminded of a module he recently added to the &#38;quot;Good List&#38;quot;. It is called &lt;a href=&#34;https://metacpan.org/module/Util::H2O&#34;&gt;Util::H2O&lt;/a&gt; and it a relatively new addition to the growing list of Perl modules on CPAN that turn &lt;code&gt;HASH&lt;/code&gt; references to blessed references with automatically generated accessor methods.&lt;/p&gt;

&lt;p&gt;Santa has, in fact, been sorely tempted to move this module to the &lt;code&gt;Very Good Module List&lt;/code&gt; since he&#38;#39;s found it so handy with all of the Perl programming he does that involves &lt;code&gt;HASH&lt;/code&gt; references. He finds it particularly useful when wrangling results from &lt;a href=&#34;https://metacpan.org/module/DBI&#34;&gt;DBI&lt;/a&gt;&#38;#39;s &lt;code&gt;selectall_hashref&lt;/code&gt; method, the results produced from his web scraping activities using &lt;a href=&#34;https://metacpan.org/module/Web::Scraper&#34;&gt;Web::Scraper&lt;/a&gt;, or the &lt;code&gt;HASH&lt;/code&gt; reference he gets after &lt;code&gt;decode_json&lt;/code&gt;&#38;#39;ing a block of JSON data from the different web API he uses to track the online activities everyone on his various &lt;i&gt;watch&lt;/i&gt; lists based on a new &lt;i&gt;goodness&lt;/i&gt; metric Mrs. Claus has been affectionately calling it, &lt;i&gt;Santa&#38;#39;s Credit Score&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;Just recently, Santa created this script that uses &lt;a href=&#34;https://metacpan.org/module/Util::H2O&#34;&gt;Util::H2O&lt;/a&gt; to add accessors to data &lt;i&gt;in flight&lt;/i&gt; in order to make it easier to manage the response &lt;code&gt;HASH&lt;/code&gt; reference returned by &lt;a href=&#34;https://metacpan.org/module/HTTP::Tiny&#34;&gt;HTTP::Tiny&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;strict&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;JSON&lt;/span&gt;       &lt;span class=&#34;words&#34;&gt;qw//&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;HTTP::Tiny&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw//&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Util::H2O&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# only exports &#39;h2o&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa can slip &lt;code&gt;h2o&lt;/code&gt; inline to his &lt;code&gt;GET&lt;/code&gt; request with more ease than he&#38;#39;s able to slip into a chimney! Can &lt;i&gt;you&lt;/i&gt; spot the addition of &lt;code&gt;h2o&lt;/code&gt;?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# give&#39;s Santa &#38;quot;$response-&#38;gt;content&#38;quot;, &#38;quot;$response-&#38;gt;status&#38;quot;, &#38;quot;$response-&#38;gt;success&#38;quot;, etc&lt;br /&gt;# from HTTP::Tiny&#39;s response object (pure HASH)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$http&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;HTTP::Tiny&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$response&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;h2o&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$http&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;literal&#34;&gt;q{https://jsonplaceholder.typicode.com/users}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Checking for success is clean and easy,&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# check for unsuccessful web request&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;success&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;STDERR&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{Can&#39;t get list of online persons to watch!\n}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;STDERR&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{Web request responded with with HTTP status: %d\n}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The JSON &lt;code&gt;content&lt;/code&gt; in the &lt;i&gt;HTTP&lt;/i&gt; call is also easily accessed so that it may be turned into a Perl data structure via &lt;code&gt;JSON::decode_json&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;comment&#34;&gt;# decode JSON from response content&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$json_array_ref&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;JSON::decode_json&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;comment&#34;&gt;# $json is an ARRAY reference&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case and after referencing the API response specification, Santa can see that he gets an &lt;code&gt;ARRAY&lt;/code&gt; of &lt;code&gt;HASH&lt;/code&gt; references:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  # [
  #  {
  #    &#38;quot;id&#38;quot;: 1,
  #    &#38;quot;name&#38;quot;: &#38;quot;Leanne Graham&#38;quot;,
  #    &#38;quot;username&#38;quot;: &#38;quot;Bret&#38;quot;,
  #    &#38;quot;email&#38;quot;: &#38;quot;Sincere@april.biz&#38;quot;,
  #    &#38;quot;address&#38;quot;: {
  #      &#38;quot;street&#38;quot;: &#38;quot;Kulas Light&#38;quot;,
  #      &#38;quot;suite&#38;quot;: &#38;quot;Apt. 556&#38;quot;,
  #      &#38;quot;city&#38;quot;: &#38;quot;Gwenborough&#38;quot;,
  #      &#38;quot;zipcode&#38;quot;: &#38;quot;92998-3874&#38;quot;,
  #      &#38;quot;geo&#38;quot;: {
  #        &#38;quot;lat&#38;quot;: &#38;quot;-37.3159&#38;quot;,
  #        &#38;quot;lng&#38;quot;: &#38;quot;81.1496&#38;quot;
  #      }
  #    }
  #  },
  # ...
  # ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And even though &lt;code&gt;h2o&lt;/code&gt; only works on &lt;code&gt;HASH&lt;/code&gt; references, this provides &lt;i&gt;yet another&lt;/i&gt; opportunity for Santa to use &lt;code&gt;h2o&lt;/code&gt; on each &lt;i&gt;item&lt;/i&gt; in the &lt;code&gt;ARRAY&lt;/code&gt;, which makes dealing with each person&#38;#39;s record much more jolly:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{lat, lng, name, username\n}&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$json_array_ref&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # -recurse creates deep accessors, e.g.,&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;#  $person-&#38;gt;address-&#38;gt;geo-&#38;gt;lat;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;h2o&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-recurse&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;interpolate&#34;&gt;qq{%5.4f, %5.4f, %s, %s\n}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;geo&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# deep chain of accessors from &#39;-recurse&#39;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;geo&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;lng&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;comment&#34;&gt;# deep chain of accessors from &#39;-recurse&#39;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$person&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa thinks this is such a nice interface for Perl &lt;code&gt;HASH&lt;/code&gt; references, he might even be able to convince the Easter bunny to finally get off His cotton tail and finally create that centralized database they and the Tooth Fairy can use all year long ... yanno, for distributing good stuff &lt;i&gt;only&lt;/i&gt;.&lt;/p&gt;

&lt;h2 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;With St. Nick&#38;#39;s list now complete with online usage profiles for all people, he now sets his mind on more jolly thoughts; not sugar plums and candy canes, but all the applications for which he may use &lt;code&gt;Util::H2O&lt;/code&gt; to make working with &lt;code&gt;HASH&lt;/code&gt; references &lt;i&gt;in flight&lt;/i&gt; more pleasant:&lt;/p&gt;

&lt;dl&gt;

&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/DBI&#34;&gt;DBI&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/HTTP::Tiny&#34;&gt;HTTP::Tiny&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/Web::Scraper&#34;&gt;Web::Scraper&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/Config::Tiny&#34;&gt;Config::Tiny&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/JSON&#34;&gt;JSON&lt;/a&gt;&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;dt&gt;&lt;a href=&#34;https://metacpan.org/module/Getopt::Long&#34;&gt;Getopt::Long&lt;/a&gt; (with &lt;a href=&#34;https://metacpan.org/module/Util::H2O::More&#34;&gt;Util::H2O::More&lt;/a&gt;&#38;#39;s &lt;code&gt;opt2h2o&lt;/code&gt;)&lt;/dt&gt;
&lt;dd&gt;

&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;He may even check out using the &lt;code&gt;bless&lt;/code&gt; replacement, &lt;code&gt;baptise&lt;/code&gt;, which is contained in &lt;a href=&#34;https://metacpan.org/module/Util::H2O::More&#34;&gt;Util::H2O::More&lt;/a&gt; and is like &lt;code&gt;bless&lt;/code&gt;, but gives you the ability to create accessors too!&lt;/p&gt;

&lt;p&gt;Don&#38;#39;t get on Santa&#38;#39;s &lt;i&gt;Naughty List&lt;/i&gt; by using cumbersome and chunky Perl &lt;i&gt;OOP&lt;/i&gt; frameworks when all you really need is a little H2O. Go check out &lt;a href=&#34;https://metacpan.org/module/Util::H2O&#34;&gt;Util::H2O&lt;/a&gt; and see if it&#38;#39;s right for your next Perl project or can be used to tidy up existing code!&lt;/p&gt;

&lt;p&gt;Merry Christmas to All, and to All a Good Night!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-06T00:00:00Z</updated><category term="Perl"/><author><name>oodler</name></author></entry><entry><title>Catching dreams</title><link href="http://perladvent.org/2022/2022-12-05.html"/><id>http://perladvent.org/2022/2022-12-05.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;h3 id=&#34;Listening-to-dreams&#34;&gt;Listening to dreams&lt;/h3&gt;

&lt;p&gt;During the year, some kids are writing &#38;quot;letters to Santa&#38;quot; or just sharing loudly what they want to &#38;quot;order&#38;quot; for Christmas, but it&#38;#39;s not always the case... Sometimes kids are only &lt;i&gt;dreaming&lt;/i&gt; what they want.&lt;/p&gt;

&lt;p&gt;Normally, dreaming is not the most effective way to &#38;quot;order&#38;quot; a present for Christmas, but Santa has thought of everything. There is a special room in North Pole complex for this purpose. It&#38;#39;s an all white, circular room with chairs arranged in the middle. Elves arrive at the room when it is nighttime in their assigned timezone.&lt;/p&gt;

&lt;p&gt;They bring a pen and a notebook, and they listen to children&#38;#39;s dreams and take notes.&lt;/p&gt;

&lt;h3 id=&#34;Gathering-notebooks&#34;&gt;Gathering notebooks&lt;/h3&gt;

&lt;p&gt;Elves capture notes on children&#38;#39;s dreams all year long and, hence, approaching Christmas there are plenty of notebooks to put together and add to other wishes.&lt;/p&gt;

&lt;p&gt;One of the elves had the idea to use &lt;a href=&#34;https://www.mongodb.com/&#34;&gt;MongoDB&lt;/a&gt; to store data.&lt;/p&gt;

&lt;p&gt;Santa complained MongoDB was not Perl friendly (e.g. struggles with drivers...) and has a license that can be considered by some as &#38;quot;controversial&#38;quot;... But the elves are not disciplined and decided to go with it anyway.&lt;/p&gt;

&lt;p&gt;1. First they installed MongoDB:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ sudo apt-get install mongodb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2. Then they started a shell:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ mongo
    MongoDB shell version v3.6.8
    connecting to: mongodb://127.0.0.1:27017
    MongoDB server version: 5.0.9
    &#38;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;3. The elves created a new database:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;gt; use christmas2022
    switched to db christmas2022&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;Import-dreams&#34;&gt;Import dreams&lt;/h4&gt;

&lt;p&gt;Despite being undisciplined, the elves followed a convention in their notes and all of their notebooks are all well-formatted as CSV.&lt;/p&gt;

&lt;p&gt;At the end of the night, a notebook looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    what,who,where
    bicycle,Tom,Atlanta
    Barbie,Lisa,Berlin
    Transformer,Billy,Houston
    ball,Ismail,Atlanta&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&#38;#39;s easy to import these notes into MongoDB:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ mongoimport -d christmas2022 -c gifts --type csv --file gifts.csv --headerline
    2022-08-04T09:57:42.400+0200    connected to: mongodb://localhost/
    2022-08-04T09:57:42.408+0200    4 document(s) imported successfully. 0 document(s) failed to import.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And you can quickly verify that it is imported:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    &#38;gt; db.gifts.find()
    { &#38;quot;_id&#38;quot; : ObjectId(&#38;quot;62eb96777d9a1bc25a68b25c&#38;quot;), &#38;quot;what&#38;quot; : &#38;quot;Transformer&#38;quot;, &#38;quot;who&#38;quot; : &#38;quot;Billy&#38;quot;, &#38;quot;where&#38;quot; : &#38;quot;Houston&#38;quot; }
    { &#38;quot;_id&#38;quot; : ObjectId(&#38;quot;62eb96777d9a1bc25a68b25d&#38;quot;), &#38;quot;what&#38;quot; : &#38;quot;bicycle&#38;quot;, &#38;quot;who&#38;quot; : &#38;quot;Tom&#38;quot;, &#38;quot;where&#38;quot; : &#38;quot;Atlanta&#38;quot; }
    { &#38;quot;_id&#38;quot; : ObjectId(&#38;quot;62eb96777d9a1bc25a68b25e&#38;quot;), &#38;quot;what&#38;quot; : &#38;quot;ball&#38;quot;, &#38;quot;who&#38;quot; : &#38;quot;Ismail&#38;quot;, &#38;quot;where&#38;quot; : &#38;quot;Atlanta&#38;quot; }
    { &#38;quot;_id&#38;quot; : ObjectId(&#38;quot;62eb96777d9a1bc25a68b25f&#38;quot;), &#38;quot;what&#38;quot; : &#38;quot;Barbie&#38;quot;, &#38;quot;who&#38;quot; : &#38;quot;Lisa&#38;quot;, &#38;quot;where&#38;quot; : &#38;quot;Berlin&#38;quot; }&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Using-Perl-to-access-dreams&#34;&gt;Using Perl to access dreams&lt;/h3&gt;

&lt;p&gt;To integrate this database in the North Pole code, the elves need to interact with it in Perl.&lt;/p&gt;

&lt;p&gt;Let&#38;#39;s install &lt;a href=&#34;https://metacpan.org/module/Mango&#34;&gt;Mango&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ sudo cpanm Mango&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then they can access records with Perl methods:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mango&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;feature&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw( state )&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;mango&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$m&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Mango&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;mongodb://localhost:27017&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$docs&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;mango&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;christmas2022&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;collection&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;gifts&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$doc&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$docs&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;$doc-&#38;gt;{what} for $doc-&#38;gt;{who} in $doc-&#38;gt;{where}\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it produces this kind of output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    Transformer for Billy in Houston
    bicycle for Tom in Atlanta
    ball for Ismail in Atlanta
    Barbie for Lisa in Berlin&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Give-me-dreams-from-Atlanta&#34;&gt;Give me dreams from Atlanta&lt;/h3&gt;

&lt;p&gt;When it comes time for making deliveries, Santa is interested in having records from the same area to optimize the logistics of his delivery schedule.&lt;/p&gt;

&lt;p&gt;With &lt;a href=&#34;https://metacpan.org/module/Mango&#34;&gt;Mango&lt;/a&gt;, it&#38;#39;s just a matter of adding a &#38;quot;clause&#38;quot; in the `find()` function:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$docs&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;mango&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;christmas2022&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;collection&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;single&#34;&gt;&#39;gifts&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;where&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Atlanta&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;With the elves&#38;#39; copious year-round notetaking of children&#38;#39;s dreams, Santa can count on the elves not to miss any of the children&#38;#39;s wishes for Christmas.&lt;/p&gt;

&lt;p&gt;Aided by &lt;a href=&#34;https://metacpan.org/module/Mango&#34;&gt;Mango&lt;/a&gt;, Santa and the elves can handle the list easily and at end of December deliver something you only ever dreamed of!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-05T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title>northpole.cgi</title><link href="http://perladvent.org/2022/2022-12-04.html"/><id>http://perladvent.org/2022/2022-12-04.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;As is the case in most public sector institutions, a lot of the tools at the North Pole are out of date. The elves often need to work with terrible spaghetti CGI scripts that are still around from the olden days. Quite a few of their internal tools with web interfaces are still implemented using &lt;a href=&#34;https://metacpan.org/module/CGI&#34;&gt;CGI&lt;/a&gt;, and despite the ongoing effort by the elves to port them over to &lt;a href=&#34;https://metacpan.org/module/Plack&#34;&gt;Plack&lt;/a&gt;, several of the more critical tools are still mostly untouched. After all, why change a running system?&lt;/p&gt;

&lt;p&gt;Of course the original development infrastructure has long since disappeared. Just a few Christmases ago they &#38;quot;lost&#38;quot; the last remaining CGI development box when a very desperate sysadmin somewhere in a small town in Texas in the United States wanted nothing more than a working Debian Woody machine. (Some of the elves still wonder how Santa got that bulky server into the guy&#38;#39;s stocking).&lt;/p&gt;

&lt;p&gt;The elves had to come up with an alternative.&lt;/p&gt;

&lt;h3 id=&#34;Enter-App::CGIThis&#34;&gt;Enter App::CGIThis&lt;/h3&gt;

&lt;p&gt;One of the tools the elves have been using for a long time when making websites is &lt;code&gt;http_this&lt;/code&gt;, the script that ships with &lt;a href=&#34;https://metacpan.org/module/App::HTTPThis&#34;&gt;App::HTTPThis&lt;/a&gt;. It lets them access a folder full of files from their browser by creating a simple web server via &lt;a href=&#34;https://metacpan.org/module/Plack::Runner&#34;&gt;Plack::Runner&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One clever elf recently discovered that you could also do this with CGI scripts. After a bit of tinkering they are now using &lt;a href=&#34;https://metacpan.org/module/App::CGIThis&#34;&gt;App::CGIThis&lt;/a&gt; and the &lt;code&gt;cgi_this&lt;/code&gt; command whenever they have to debug one of these old CGI scripts.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ cgi_this
    Exporting &#38;#39;.&#38;#39;, available at:
    http://127.0.0.1:3000/

    Found the following scripts:
        http://127.0.0.1:3000/hello.cgi&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If run with no arguments, it simply turns the whole current directory into a CGI script serving web server that listens on port 3000. The elves like this to test quick fixes to the configuration-heavy scripts that they haven&#38;#39;t managed to migrate yet.&lt;/p&gt;

&lt;p&gt;The two remaining original CGI elves think this is not necessary, because they could of course make these changes in production, claiming the younger elf generation is too scared to get things done, but luckily the head elf is heaving none of that. Instead, these two now use &lt;a href=&#34;https://metacpan.org/module/cgi_this&#34;&gt;cgi_this&lt;/a&gt; with the &lt;code&gt;--cgi-bin&lt;/code&gt; flag, which makes the URLs look more like what they are used to.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ cgi_this --cgi-bin
    Exporting &#38;#39;.&#38;#39;, available at:
    http://127.0.0.1:3000/

    Found the following scripts:
        http://127.0.0.1:3000/cgi-bin/hello.cgi&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, despite the selfless act of giving their last old machine to a fellow techie in need, they can still safely test their work whenever they have to debug one of the old scripts.&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-04T00:00:00Z</updated><category term="Perl"/><author><name>Julien Fiegehenn</name></author></entry><entry><title>Santa is on GitHub</title><link href="http://perladvent.org/2022/2022-12-03.html"/><id>http://perladvent.org/2022/2022-12-03.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Last year, Santa lost his mind with missing gifts, hence he gathered a council with the elves and they decided to make the process more &#38;quot;rigorous&#38;quot; in 2023. This year, it has been decided to use a GitHub repository to organize and track the preparation of gifts for Christmas.&lt;/p&gt;

&lt;p&gt;Santa has created a repository called &#38;quot;gifts&#38;quot; in his account &#38;quot;santa&#38;quot;.&lt;/p&gt;

&lt;p&gt;Each time an elf has finished preparing a toy, he commits a quick note and a helpful message, e.g. &#38;quot;A cowboy for James&#38;quot;.&lt;/p&gt;

&lt;p&gt;So far, &#38;quot;What is the relation with Perl?&#38;quot; you might ask. It&#38;#39;s just a great opportunity to discover and use &lt;a href=&#34;https://metacpan.org/pod/Pithub&#34;&gt;Pithub&lt;/a&gt; :)&lt;/p&gt;

&lt;h3 id=&#34;Look-at-last-prepared-toys-commits&#34;&gt;Look at last prepared toys (commits)&lt;/h3&gt;

&lt;p&gt;Every once in a while, Santa -- or the elves themselves -- want to check produced items, so they use Pithub for that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::Repos&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$repos&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::Repos&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$repos&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;commits&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;santa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;repo&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gifts&#39;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;next&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It produces this kind of output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    A bicycle for Tom
    A Barbie for Lisa
    A Transformer for Billy&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Gifts-should-remain-a-surprise&#34;&gt;Gifts should remain a surprise!&lt;/h3&gt;

&lt;p&gt;But wait, a public GitHub repository means any little young programmer frequenting GitHub will know in advance his Christmas present?! This is not good at all, so Santa decided to change visibility of the repository to &#38;quot;private&#38;quot;.&lt;/p&gt;

&lt;p&gt;It seemed at first to work well but, sadly, even though Santa and the elves could still access the repo via the GitHub UI, they were no longer able to list the commits via Pithub.&lt;/p&gt;

&lt;p&gt;They started to debug by adding some error handling:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Error: %s\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;status_line&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This confirmed that the repository is &#38;quot;not visible&#38;quot; with &lt;code&gt;Error: 404 Not Found&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, there is a solution to this: use a &#38;quot;token&#38;quot; to authenticate the access!&lt;/p&gt;

&lt;p&gt;The elves asked Santa to create one in the GitHub UI from &lt;a href=&#34;https://github.com/settings/tokens&#34;&gt;settings/tokens&lt;/a&gt;:&lt;/p&gt;

&lt;center&gt;&lt;img src=&#34;pat.png&#34; alt=&#34;GitHub Personal Access Token&#34;&gt;&lt;/center&gt;

&lt;p&gt;The elves provided the generated token to the Pithub constructor and regained access to the private repository:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::Repos&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$repos&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::Repos&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ghp_pwBR12&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$repos&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;commits&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;santa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;repo&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gifts&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Error: %s\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;status_line&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;next&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$row&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using a token also allows you to increase your GitHub API rate limit.&lt;/p&gt;

&lt;h3 id=&#34;Sending-gifts&#34;&gt;Sending gifts&lt;/h3&gt;

&lt;p&gt;To alert when a toy is about to be delivered, the elves are opening Pull Requests, and they once again use Pithub for this.&lt;/p&gt;

&lt;p&gt;Each elf is doing one Pull Request per family, and after Santa actually delivers the toys he merges the Pull Requests. (Don&#38;#39;t ask me to elaborate a full branching model).&lt;/p&gt;

&lt;p&gt;It&#38;#39;s a little bit of work, but once again very easy and straightforward:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::PullRequests&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$pull&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Pithub::PullRequests&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;token&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ghp_pwBR12&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Create PR from [family-anderson] to [main]\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$pull&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;create&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;user&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;santa&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;repo&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;gifts&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;data&lt;/span&gt;   &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;base&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;main&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;body&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Delivery to family Anderson&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;head&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;family-anderson&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Family Anderson&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;unless&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Error: %s\n&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$result&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;status_line&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;Conclusion&#34;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Thanks to Pithub, the elves were able to easily interact with the GitHub API for both reading and writing.&lt;/p&gt;

&lt;p&gt;If Christmas is once again a success this year, some of the credit should go to &lt;a href=&#34;https://metacpan.org/pod/Pithub&#34;&gt;Pithub&lt;/a&gt;!&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-03T00:00:00Z</updated><category term="Perl"/><author><name>Thibault DUPONCHELLE</name></author></entry><entry><title>MooseX::Getopt saves Christmas</title><link href="http://perladvent.org/2022/2022-12-02.html"/><id>http://perladvent.org/2022/2022-12-02.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;&#38;quot;It&#38;#39;s done, sir.&#38;quot; An elf that had the fuzzy, out of focus look of a developer who&#38;#39;d been awake since the beginning of Advent stuck their head round Santa&#38;#39;s door. &#38;quot;New, uh, present delivery planning script, like you asked. No more gender-specific toys, and naughty or nice checks are now optional. And it feeds the new delivery plotting script or your SledNav.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Hrm. OK.&#38;quot; Santa nodded, distractedly. &#38;quot;I&#38;#39;ll take a look later.&#38;quot;&lt;/p&gt;

&lt;p&gt;They blinked. &#38;quot;OK. I&#38;#39;ll just... uh... go crash for a bit.&#38;quot; Looking like they would do so before they made it much further down the corridor, they stumbled out.&lt;/p&gt;

&lt;h3 id=&#34;Some-while-later&#34;&gt;Some while later:&lt;/h3&gt;

&lt;p&gt;Santa brought up a shell prompt. &#38;quot;Hrmmm. Let&#38;#39;s see. Ahah.&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ delivery_plan
    Usage: delivery_plan [options]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Saint Nick harumphed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ delivery_plan --help
    Usage: delivery_plan [options]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#38;quot;ERNEST!&#38;quot;&lt;/p&gt;

&lt;p&gt;Santa&#38;#39;s right-hand elf hurried in. &#38;quot;Yes boss?&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;What in the name of Christmas am I supposed to do to get this to run?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest peered over Santa&#38;#39;s shoulder. &#38;quot;Is that the new delivery script? I better take a look - the dev is snoring fit to be heard in Bethlehem, and I don&#38;#39;t think they&#38;#39;ll wake up before New Year.&#38;quot;&lt;/p&gt;

&lt;h3 id=&#34;Command-line-options&#34;&gt;Command line options&lt;/h3&gt;

&lt;p&gt;Ernest sighed, back at his desk. &#38;quot;OK. No marks for hand-rolling the option parsing...&#38;quot; He copied the main script to &lt;code&gt;NorthPole/DeliveryPlan.pm&lt;/code&gt; and edited it, removing the crufty command line parsing code and wrapping the remainder of the body of the script in a method.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;NorthPole::DeliveryPlan&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.36&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Moose&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;MooseX::Getopt&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;feature&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;signatures&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;run&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;    # body of script&lt;br /&gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa&#38;#39;s right-hand elf&#38;#39;s right-hand elf peered curiously over Ernest&#38;#39;s shoulder. &#38;quot;Whatcha doing?&#38;quot; she asked.&lt;/p&gt;

&lt;p&gt;He sighed. &#38;quot;Fixing the new delivery planning script. &lt;i&gt;Someone&lt;/i&gt; committed it without even basic usage docs.&#38;quot; Ernest opened a new &lt;code&gt;delivery_plan&lt;/code&gt; file for the script itself. &#38;quot;Here. Watch.&#38;quot;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;NorthPole::DeliveryPlan&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$app&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;NorthPole::DeliveryPlan&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new_with_options&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;symbol&#34;&gt;$app&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#38;quot;Hang on.&#38;quot; She frowned. &#38;quot;Didn&#38;#39;t legal just say yesterday we couldn&#38;#39;t use Moose?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest permitted himself a snort which precisely defined his opinion of legal. &#38;quot;Internal software. None of their business.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Ok, so - &lt;code&gt;new_with_options&lt;/code&gt; essentially uses the attribute definitions on the class to define how it parses any command line options, and then passes them as constructor arguments to the object. So...&#38;quot; he went back to &lt;code&gt;NorthPole::DeliveryPlan&lt;/code&gt; &#38;quot;We can add a &lt;code&gt;--nice_check&lt;/code&gt; switch by just adding a &lt;code&gt;nice_check&lt;/code&gt; attribute...&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;nice_check&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Bool&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;She chuckled. &#38;quot;Oh! Neat. The command line switch value ends up on the attribute, so you can just check it with &lt;code&gt;$self-&#38;gt;nice_check&lt;/code&gt;, right? Let me guess - if you set &lt;code&gt;required =&#38;gt; 1&lt;/code&gt;, it&#38;#39;s a mandatory parameter?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest nodded, &#38;quot;In one. And it also gives you &lt;code&gt;--no-nice_check&lt;/code&gt; for free because it&#38;#39;s a &lt;code&gt;Bool&lt;/code&gt;.&#38;quot;&lt;/p&gt;

&lt;p&gt;She nodded, then went on. &#38;quot;And... Wow, so, ok... waitaminnit... if it&#38;#39;s a &lt;code&gt;Str&lt;/code&gt; or a &lt;code&gt;Num&lt;/code&gt;, then, the parameter takes a value?&#38;quot; Ernest hid a smile and carried on typing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;country&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Str&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;required&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#38;quot;Like that, you mean.&#38;quot; He grinned. &#38;quot;Exactly so - that handles &lt;code&gt;--country=GB&lt;/code&gt;, for example.&#38;quot;&lt;/p&gt;

&lt;p&gt;She frowned. &#38;quot;Didn&#38;#39;t Santa say he wanted to process multiple countries at once?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest &#38;#39;mmhm&#38;#39;-ed. &#38;quot;He did, yes. We can do that easily enough.&#38;quot; He edited the definition.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;country&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ArrayRef&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;required&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#38;quot;There. Just pass &lt;code&gt;--country&lt;/code&gt; multiple times and you can pick the results out of &lt;code&gt;$self-&#38;gt;country&lt;/code&gt;.&#38;quot;&lt;/p&gt;

&lt;p&gt;She clapped, delightedly. &#38;quot;Neato. Ok, but what about documentation?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest chuckled. &#38;quot;Ok, fair. That &lt;i&gt;was&lt;/i&gt; the original point of this. So. We have &lt;code&gt;Getopt::Long::Descriptive&lt;/code&gt; installed anyway, since some people &lt;i&gt;do&lt;/i&gt; actually remember to use it, so all you have to do is add &lt;code&gt;documentation&lt;/code&gt; to the attribute definition and the role will respond to &lt;code&gt;--help&lt;/code&gt;, &lt;code&gt;--usage&lt;/code&gt; or &lt;code&gt;-?&lt;/code&gt; with the docs for all the options.&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;output&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;            &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt;           &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Str&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;required&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;documentation&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;output format - one of &#39;plot&#39; or &#39;slednav&#39;&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;She frowned. &#38;quot;Can&#38;#39;t you make it just accept those two values?&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Oh... yeah. Sure. We&#38;#39;ll just create an &lt;code&gt;enum&lt;/code&gt; for them, and because that&#38;#39;s just a subtype of &lt;code&gt;Str&lt;/code&gt; it falls out in the wash.&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Moose::Util::TypeConstraints&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;OutputFormat&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;words&#34;&gt;qw/ plot slednav /&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;output&#39;&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;            &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;rw&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt;           &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;OutputFormat&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;required&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;documentation&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;output format - one of &#39;plot&#39; or &#39;slednav&#39;&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;He added the rest of the documentation, and another option. &#38;quot;And then... here we go.&#38;quot;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    $ delivery_plan
    Mandatory parameter &#38;#39;country&#38;#39; missing in call to &#38;quot;eval&#38;quot;

    usage: delivery_plan [-?h] [long options...]
        -h -? --usage --help  Prints this usage information.
        --[no-]nice_check     DEPRECATED: only deliver to those who have been
                              nice.
        --[no-]gender         DEPRECATED: gender-specific presents
        --country STR...      which countries to deliver to
        --output STR          output format - one of &#38;#39;plot&#38;#39; or &#38;#39;slednav&#38;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&#38;quot;If its a more complex type and the behaviour on the parent type isn&#38;#39;t enough, there&#38;#39;s a helper function to update the type map, &lt;code&gt;add_option_type_to_map&lt;/code&gt;, but you can read up on that in the module docs yourself.&#38;quot; Ernest grinned at her. &#38;quot;And to be fair, some of the type-checking errors are a bit &lt;code&gt;Moose&lt;/code&gt;-y, but...&#38;quot;&lt;/p&gt;

&lt;p&gt;She laughed. &#38;quot;I know, I know. &#38;#39;Patches welcome.&#38;#39;&#38;quot;&lt;/p&gt;

&lt;p&gt;He laughed &#38;quot;Exactly. Now scoot, while I test this and push it.&#38;quot;&lt;/p&gt;

&lt;h3 id=&#34;Epilogue&#34;&gt;Epilogue&lt;/h3&gt;

&lt;p&gt;Ernest fired off an email.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    Hi,

    When you wake up, please check the commit log for the delivery plan script,
    and learn from it. The Big Red Boss doesn&#38;#39;t have time to read source code
    to figure out what things we give him are meant to do.

    Also, how on Earth did you manage to come up with an O(N) solution
    to the travelling salesman problem? Magic?

    E.&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;</summary><updated>2022-12-02T00:00:00Z</updated><category term="Perl"/><author><name>Mike Whitaker</name></author></entry><entry><title>Silent Mite</title><link href="http://perladvent.org/2022/2022-12-01.html"/><id>http://perladvent.org/2022/2022-12-01.html</id><summary type="html">&lt;div class=&#39;pod&#39;&gt;&lt;p&gt;Ernest the Elf sat outside Santa&#38;#39;s office. It was August, a time of year the boss was usually less stressed. A good thing, as he had some bad news to deliver.&lt;/p&gt;

&lt;p&gt;The door opened and an elf that Ernest vaguely recognized from the staff lunch room emerged and hastened down the hall. A booming voice came from inside the office. &#38;quot;Next!&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest hurried in and the old man gestured for him to take a seat. This was his first time meeting Santa in person since he&#38;#39;d started with the company. &#38;quot;Sir, I&#38;#39;m afraid I have some bad news about the ninja robot aliens.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Please,&#38;quot; Santa said, &#38;quot;no need to call me &#38;#39;Sir&#38;#39;. Everybody just calls me &#38;#39;Santa&#38;#39;. So what&#38;#39;s going on with the ninja robot aliens? I know they&#38;#39;re going to be popular. It&#38;#39;s summer and I&#38;#39;m already getting letters. You&#38;#39;re heading up the software development for them, right?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest nodded. &#38;quot;Yes, we&#38;#39;ve been writing it using Moose.&#38;quot; He paused. The silence was interrupted by Rudolf&#38;#39;s honks outside in the field.&lt;/p&gt;

&lt;p&gt;&#38;quot;Appropriate!&#38;quot; Santa laughed, his belly shaking like a bowlful of jelly.&lt;/p&gt;

&lt;p&gt;&#38;quot;Indeed,&#38;quot; said Ernest. &#38;quot;But legal have just told us we can&#38;#39;t use Moose. No third party code can be bundled unless it has a warranty.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Legal,&#38;quot; grumbled the old man. &#38;quot;You know last year they tried telling me I can&#38;#39;t drink alcohol at every single house I stop at while operating a sophisticated flying sleigh? Bunch of killjoys. Are you using the metaobject protocol?&#38;quot; Santa asked, displaying a knowledge of Perl programming which surprised Ernest.&lt;/p&gt;

&lt;p&gt;&#38;quot;No,&#38;quot; said Ernest. &#38;quot;But switching to Moo isn&#38;#39;t an option anyway, because that doesn&#38;#39;t have a warranty either. We can only use core Perl because our embedded hardware support contract covers that.&#38;quot;&lt;/p&gt;

&lt;p&gt;Santa frowned. &#38;quot;I guess that would need a big rewrite. Is there enough time before December?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest shook his head. &#38;quot;Not if we want to leave enough time for code reviews, acceptance testing, quality assurance...&#38;quot; His voice trailed off.&lt;/p&gt;

&lt;p&gt;&#38;quot;Let&#38;#39;s take a look at the code,&#38;quot; Santa suggested, pulling up a fresh checkout of the repository and turning his screen around so Ernest could go through it with him. He opened up a random class.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.24&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;experimental&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;signatures&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Robot::Alien::Ninja::Face&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Moose&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Time::HiRes&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;sleep&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Robot::Alien::Ninja::Face&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;ro&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;ArrayRef[$eye_class]&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;builder&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;_build_eyes&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;_build_eyes&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;blink&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%arg&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;close&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@*&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.2&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@*&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;wink&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;%arg&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eye&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.4&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;__PACKAGE__&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;meta&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;make_immutable&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa nodded while reading it. &#38;quot;Pretty clean code.&#38;quot; His fingers flew across the keyboard, tapping in a few commands.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   cd ~/src/Robot-Alien-Ninja
   cpanm Mite
   mite init Robot::Alien::Ninja
   mite compile&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;He then edited Face.pm replacing &lt;code&gt;use Moose&lt;/code&gt; with &lt;code&gt;use Robot::Alien::Ninja::Mite -all&lt;/code&gt;, and replaced &lt;code&gt;__PACKAGE__-&#38;gt;meta-&#38;gt;make_immutable&lt;/code&gt; with &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;He ran &lt;code&gt;mite compile&lt;/code&gt; again and then started the test suite. It all passed.&lt;/p&gt;

&lt;p&gt;&#38;quot;So will legal let us distribute Mite?&#38;quot; Ernest asked, confused.&lt;/p&gt;

&lt;p&gt;&#38;quot;That&#38;#39;s the beauty of it!&#38;quot; Santa smiled. &#38;quot;Your code doesn&#38;#39;t depend on Mite. It depends on Robot::Alien::Ninja::Mite, which is under 300 lines long and you can audit in a few hours. Mite itself is a tool that lives on your development machine, but doesn&#38;#39;t need to be installed on the ninja robot pirates.&#38;quot;&lt;/p&gt;

&lt;p&gt;&#38;quot;Aliens,&#38;quot; said Ernest.&lt;/p&gt;

&lt;p&gt;&#38;quot;Of course, aliens,&#38;quot; said Santa, making a mental note for what was sure to be &lt;i&gt;next&lt;/i&gt; year&#38;#39;s hit toy. &#38;quot;Think about it this way. You use, what, emacs to edit your code?&#38;quot;&lt;/p&gt;

&lt;p&gt;Ernest nodded.&lt;/p&gt;

&lt;p&gt;&#38;quot;Well, the end user doesn&#38;#39;t need emacs to run your code. Mite is just a development tool.&#38;quot;&lt;/p&gt;

&lt;p&gt;It began to make sense to Ernest. &#38;quot;Does Mite support everything Moose does?&#38;quot;&lt;/p&gt;

&lt;p&gt;Santa shook his head. &#38;quot;There are some limitations, but skimming through your code, it should handle most of what you need. It has attributes with type constraints and coercion, triggers, defaults, and delegation; it has method modifiers; it has roles. In fact, it even has some features Moose doesn&#38;#39;t have.&#38;quot; His fingers flew into a blur on the keyboard.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;code-listing&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;version&#34;&gt;v5.24&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;pragma&#34;&gt;experimental&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;signatures&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Robot::Alien::Ninja::Face&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Robot::Alien::Ninja::Mite&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;-all&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;Time::HiRes&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;sleep&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;Robot::Alien::Ninja::Face&#39;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;has&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;is&lt;/span&gt;      &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;ro&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;isa&lt;/span&gt;     &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;double&#34;&gt;&#38;quot;Tuple[ $eye_class, $eye_class ]&#38;quot;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;builder&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye_class&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;comment&#34;&gt;# XXX: add eye patch support?&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;signature_for&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;blink&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;named&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;PositiveNum&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.2&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;blink&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;close&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@*&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;magic&#34;&gt;$_&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;cast&#34;&gt;@*&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;word&#34;&gt;signature_for&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;wink&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;named&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;PositiveNum&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;       &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;0.4&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;eye&lt;/span&gt;  &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;single&#34;&gt;&#39;PositiveOrZeroInt&#39;&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&#38;gt;&lt;/span&gt; &lt;span class=&#34;number&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;structure&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;keyword&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;word&#34;&gt;wink&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;{&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;keyword&#34;&gt;my&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt; &lt;span class=&#34;operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$self&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eyes&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;eye&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;word&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;symbol&#34;&gt;$arg&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;structure&#34;&gt;);&lt;/span&gt;&lt;br /&gt;&#38;nbsp;&#38;nbsp;&#38;nbsp;&lt;span class=&#34;symbol&#34;&gt;$eye&lt;/span&gt;&lt;span class=&#34;operator&#34;&gt;-&#38;gt;&lt;/span&gt;&lt;span class=&#34;word&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&#34;structure&#34;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;operator&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&#34;number&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;structure&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Santa ran &lt;code&gt;mite compile&lt;/code&gt; and ran the test suite again.&lt;/p&gt;

&lt;p&gt;Ernest watched as it passed. &#38;quot;Do you mind committing that into a branch? I&#38;#39;d like to go back to my workstation and test it out some more.&#38;quot;&lt;/p&gt;

&lt;p&gt;Santa nodded. &#38;quot;On your way out, could you send in the next elf?&#38;quot;&lt;/p&gt;

&lt;/div&gt;</summary><updated>2022-12-01T00:00:00Z</updated><category term="Perl"/><author><name>Toby Inkster</name></author></entry></feed>