<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 🌌 Sébastien Feugère ☔</title>
    <description>The latest articles on DEV Community by 🌌 Sébastien Feugère ☔ (@smonff).</description>
    <link>https://dev.to/smonff</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F171647%2F6334752f-e022-4815-8ceb-09a969c11f98.jpeg</url>
      <title>DEV Community: 🌌 Sébastien Feugère ☔</title>
      <link>https://dev.to/smonff</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smonff"/>
    <language>en</language>
    <item>
      <title>Preload Data::Printer and avoid polluting your code with debug symbols</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Thu, 08 Feb 2024 19:00:00 +0000</pubDate>
      <link>https://dev.to/smonff/preload-dataprinter-and-avoid-polluting-your-code-with-debug-symbols-4h5a</link>
      <guid>https://dev.to/smonff/preload-dataprinter-and-avoid-polluting-your-code-with-debug-symbols-4h5a</guid>
      <description>&lt;p&gt;When I work, I tend to have a lot of boilerplate. I am a great user of &lt;a href="https://metacpan.org/pod/Data::Printer" rel="noopener noreferrer"&gt;Data::Printer&lt;/a&gt; for debugging. There is no way I wouldn't use it, even on the smallest project. Usually, I have this on all my projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Data::&lt;/span&gt;&lt;span class="nv"&gt;Printer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Fellow &lt;a href="https://metacpan.org/author/SYSPETE" rel="noopener noreferrer"&gt;Peter&lt;/a&gt; coworker saw me doing that once and said I liked typing too much: only &lt;code&gt;use DDP&lt;/code&gt; was enough.&lt;/p&gt;

&lt;p&gt;Later I learned &lt;a href="https://metacpan.org/pod/Data::Printer#Using-p()-in-some/all-of-your-loaded-modules" rel="noopener noreferrer"&gt;another solution was provided&lt;/a&gt; in the DDP documentation.&lt;/p&gt;

&lt;p&gt;It's possible to call &lt;code&gt;::p&lt;/code&gt;instead of &lt;code&gt;p()&lt;/code&gt;: &lt;code&gt;::p&lt;/code&gt; doesn't require to &lt;code&gt;use&lt;/code&gt; the module first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For getting this to work, it's necessary to &lt;em&gt;preload&lt;/em&gt; the module through command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;perl &lt;span class="nt"&gt;-MDDP&lt;/span&gt; script.pl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The good thing is that if we forget debug symbols in a module that is going to reach deployment pipelines or the CPAN (assuming we don't have other tools configured complaining about that), it will trigger a compile-time failure without the &lt;code&gt;-M&lt;/code&gt; option, making it easier to catch.&lt;/p&gt;

&lt;p&gt;Note that it also works well for tests with &lt;code&gt;Test2::Harness&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yath &lt;span class="nt"&gt;-MDDP&lt;/span&gt; 01_test.t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cryptocurrency</category>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>Demand Data::Printer to dump politely if it doesn't want to</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Wed, 07 Feb 2024 11:00:58 +0000</pubDate>
      <link>https://dev.to/smonff/demand-dataprinter-to-dump-politely-if-it-doesnt-want-to-5hdh</link>
      <guid>https://dev.to/smonff/demand-dataprinter-to-dump-politely-if-it-doesnt-want-to-5hdh</guid>
      <description>&lt;p&gt;If your project got objects that use the following methods names:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;to_string()&lt;/code&gt;, &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;as_string()&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stringify()&lt;/code&gt;,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... &lt;a href="https://metacpan.org/pod/Data::Printer" rel="noopener noreferrer"&gt;Data::Printer&lt;/a&gt; might not behave as expected... It will dump the &lt;em&gt;"stringified"&lt;/em&gt; object (as defined in your own code, possibly  &lt;code&gt;$self-&amp;gt;name&lt;/code&gt; or something slightly more complicated).&lt;/p&gt;

&lt;p&gt;It's possible to disable that feature on &lt;code&gt;p()&lt;/code&gt; call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;$fancy_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;stringify&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But honestly, that's too much typing verbosity. I prefer, to have a &lt;code&gt;~/.dataprinter&lt;/code&gt; file containing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;class&lt;/span&gt;.&lt;span class="n"&gt;stringify&lt;/span&gt; = &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's very convenient, for example, to automate the creation of this file in development environment (e.g. Docker containers). I usually add the following to my &lt;code&gt;Dockerfile&lt;/code&gt;s :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'class.stringify = 0'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.dataprinter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://metacpan.org/pod/Data::Printer#Making-your-classes-DDP-aware-(without-adding-any-dependencies!)" rel="noopener noreferrer"&gt;Data::Printer perldoc&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Finally, if your object implements string overload or provides a method called "to_string", "as_string" or "stringify", Data::Printer will use it. To disable this behaviour, set &lt;code&gt;class.stringify = 0&lt;/code&gt; on your &lt;code&gt;.dataprinter&lt;/code&gt; file, or call &lt;code&gt;p()&lt;/code&gt; with &lt;code&gt;class =&amp;gt; { stringify =&amp;gt; 0 }&lt;/code&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>perl</category>
      <category>datastructures</category>
      <category>debugging</category>
      <category>dumper</category>
    </item>
    <item>
      <title>The spooky CSS in Perl toolkit</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Thu, 28 Dec 2023 15:17:10 +0000</pubDate>
      <link>https://dev.to/smonff/css-in-perl-1pl8</link>
      <guid>https://dev.to/smonff/css-in-perl-1pl8</guid>
      <description>&lt;p&gt;Some people are really going to love that: a spooky inline CSS  helper for composing Outlook messages in a Perl application!&lt;/p&gt;

&lt;p&gt;Most websites those days are &lt;em&gt;SPA applications&lt;/em&gt; that render on the front-side, or a mixture of backend and frontend rendering. There is also this trend of &lt;a href="https://cssinjs.org/" rel="noopener noreferrer"&gt;CSS in JavaScript also knowns as JSS&lt;/a&gt; that is debatable for the simplest projects (makes everything overcomplicated), but in for more complex applications, can be justified and very useful.&lt;/p&gt;

&lt;p&gt;Anyway, I use a lot of server side rendering. I mean, the old-school way you know, I serve HTML, CSS, and JavaScript separately.&lt;/p&gt;

&lt;p&gt;A couple of years ago, I encountered one of those specific cases where it was useful to generate the CSS from some Perl code. We developed a crawler that helped us to interact with our in house project management API, so that we could send alerts to our colleagues when requirements had not been delivered and deadlines approached. Day minus 7, minus 3 and minus 1. And those colleagues used old versions of Outlook, so it was obligatory tables based emails, you know, those who have all kind of style and non-standard attributes all over the tags. It's actually not even standard CSS, it is Outlook specific style attributes in HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt;
    &lt;span class="na"&gt;align=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
    &lt;span class="na"&gt;bgcolor=&lt;/span&gt;&lt;span class="s"&gt;"#FFFFFF"&lt;/span&gt;
    &lt;span class="na"&gt;cellpadding=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
    &lt;span class="na"&gt;cellspacing=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w600"&lt;/span&gt;
    &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In such a situation, the tags and style are totally mixed. There is no separation of concerns any more.&lt;/p&gt;

&lt;p&gt;There are tools (e.g. &lt;a href="https://get.foundation/emails.html" rel="noopener noreferrer"&gt;Foundation Emails&lt;/a&gt;) for managing these kinds of beautiful things, but the integration with the crawler was more complicated than developing our own.&lt;/p&gt;

&lt;p&gt;I thought of the &lt;em&gt;CSS in JS&lt;/em&gt; thing and decided to implement a quick helper to inject the styled tags in appropriate places. Note that it starts to be interesting because when you compose such things, you have the same values repeated from dozens to hundreds of tags. And believe me, I had colleagues who really needed this automated, they would be asked to do it by hand otherwise. That's how things worked, in this company, e.g. there were no SCM tools and each &lt;em&gt;“programmer”&lt;/em&gt; worked on their own repository, that were &lt;em&gt;“merged”&lt;/em&gt; every few years. Also, production had hundreds of duplicates of the same app, but not the way you think of. Anyway, I'm digressing.&lt;/p&gt;

&lt;p&gt;What I wanted was a nicely structured application, with separation of concerns, templates, no duplicated code and easy to maintain, although in the end it was for producing spooky inline CSS. This is how we would generate the previous HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w600&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
 &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basis of our toolkit is the &lt;code&gt;Mojolicious::Plugin::Email::Style::CSS&lt;/code&gt; module that is strictly the same as the principle of &lt;em&gt;CSS in&lt;br&gt;
JS&lt;/em&gt; except it is &lt;em&gt;CSS in Perl&lt;/em&gt; (I can hear some people crying, but this thing got designed with Outlook 2016 in mind, sorry).&lt;/p&gt;

&lt;p&gt;It contains a list of constants that can be extended and nested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Mojolicious::Plugin::Email::Style::&lt;/span&gt;&lt;span class="nv"&gt;CSS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojo::&lt;/span&gt;&lt;span class="nv"&gt;Base&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;PALETTE&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;INFO&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#4ECA47&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
  &lt;span class="s"&gt;WARNING&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#F0964B&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
  &lt;span class="s"&gt;DANGER&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#F52930&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
  &lt;span class="s"&gt;WHITE&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="s"&gt;ALIGNCENTER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-align: center&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="s"&gt;CELLZERO&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;cellpadding&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="s"&gt;cellspacing&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="s"&gt;HEADER_COLOR&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;bgcolor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;INFO&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;bgcolor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;WARNING&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;bgcolor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;DANGER&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="s"&gt;MAIN_WIDTH&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only a couple of &lt;a href="https://perldoc.perl.org/constant" rel="noopener noreferrer"&gt;constant&lt;/a&gt; hashes that are structured as a &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;Sass file&lt;/a&gt; would be. I means: CSS with variables.&lt;/p&gt;

&lt;p&gt;We also have a &lt;code&gt;css&lt;/code&gt; subroutine that will take care of the &lt;em&gt;“preprocessing”&lt;/em&gt;. It now looks even more like CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt;&lt;span class="p"&gt;( $self ) {&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;align-center&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;ALIGNCENTER&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;%*&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="s"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;leftmargin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;topmargin&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;marginwidth&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;marginheight&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;bgcolor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;WHITE&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;border&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="nv"&gt;CELLZERO&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;%*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;align&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;bgcolor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;WHITE&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="s"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;MAIN_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;CELLZERO&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;%*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;border&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="s"&gt;align&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
      &lt;span class="nv"&gt;HEADER_COLOR&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;alert_occurence&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;%*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;MAIN_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;CELLZERO&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;%*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;PALETTE&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;WHITE&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="s"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color: #FFFFFF; &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-family: Arial, Gotham, 'Helvetica Neue', Helvetica,'sans-serif'; &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 250%;&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nbsp-top-margin&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size: 17px; line-height: 17px&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CSS.pm&lt;/code&gt; module also &lt;code&gt;has&lt;/code&gt; an &lt;code&gt;alert_occurence&lt;/code&gt; attribute so that we can send appropriate content and dynamically style the email depending on the emergency of the situation (day minus &lt;code&gt;7&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, or &lt;code&gt;1&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojo::&lt;/span&gt;&lt;span class="nv"&gt;Base&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert_occurence&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CSS.pm&lt;/code&gt; module is registered as a &lt;code&gt;inline&lt;/code&gt; helper in our &lt;code&gt;Mojolicious::Plugin::Email::Style&lt;/code&gt; plugin, so that it can be consumed in &lt;a href="https://docs.mojolicious.org/Mojo/Template" rel="noopener noreferrer"&gt;Mojo templates&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojo::&lt;/span&gt;&lt;span class="nv"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mojolicious::Plugin&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojolicious::Plugin::Email::Style::&lt;/span&gt;&lt;span class="nv"&gt;CSS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt; &lt;span class="p"&gt;( $self, $app, $conf ) {&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Mojolicious::Plugin::Email::Style::&lt;/span&gt;&lt;span class="nv"&gt;CSS&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;( $self, $key ) {&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$style&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;css&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;%*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin is then loaded in a larger application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Email::&lt;/span&gt;&lt;span class="nv"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojo::&lt;/span&gt;&lt;span class="nv"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mojolicious&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;startup&lt;/span&gt; &lt;span class="p"&gt;( $app ) {&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alerts::Api::Plugin::Style&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Templates
&lt;/h1&gt;

&lt;p&gt;Here are the main templates used for the Outlook messages. This is the global layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="nv"&gt;DOCTYPE&lt;/span&gt; &lt;span class="nv"&gt;html&lt;/span&gt; &lt;span class="nv"&gt;PUBLIC&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-//W3C//DTD XHTML 1.0 Strict//EN&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;html&lt;/span&gt; &lt;span class="nv"&gt;xmlns:v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;urn:schemas-microsoft-com:vml&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;meta&lt;/span&gt; &lt;span class="nv"&gt;http&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/html; charset=utf-8&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;meta&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width=device-width; initial-scale=1.0; maximum-scale=1.0;&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;Alert&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;include&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;layouts/style&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nv"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nv"&gt;html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is how we use our &lt;code&gt;inline&lt;/code&gt; helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;layout&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;outlook&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
  &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;tbody&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
    &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="sr"&gt;tr =&amp;gt; begin
      %= t td =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt; &lt;span class="o"&gt;~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w600&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
          &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;tbody&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nv"&gt;header&lt;/span&gt; &lt;span class="o"&gt;~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w600&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header-table&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
              &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;tbody&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
                &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="sr"&gt;tr =&amp;gt; begin
                  %= t td =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;align&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="p"&gt;')&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;tbody&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                      &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nv"&gt;top&lt;/span&gt; &lt;span class="nv"&gt;margin&lt;/span&gt; &lt;span class="o"&gt;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
                      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;tr&amp;gt;
                        %= t td =&amp;gt; ( inline 'nbsp-top-margin' ) =&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
                          &lt;span class="nv"&gt;&amp;amp;nbsp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
                      &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="sr"&gt;tr&amp;gt;
                      &amp;lt;!-- logo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --&amp;gt;
                      %= include 'fragment/logo'
                      &amp;lt;tr&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;%=&lt;/span&gt; &lt;span class="nv"&gt;t&lt;/span&gt; &lt;span class="s"&gt;td&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;align&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;begin&lt;/span&gt;
                          &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="c1"&gt;# include 'fragment/hi'&lt;/span&gt;
                        &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
                      &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nb"&gt;tr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nv"&gt;tbody&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
                &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
              &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
            &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
          &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
        &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
      &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
    &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
  &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="c1"&gt;#= include 'fragment/alert/first'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The examples for this blog post are very simple. Such old-style Outlook emails can use very-very verbose attributes and be duplicated all over the place, especially if you generate content. You obviously don't want that to be edited by hand. My idea with this project was to avoid that someone had to edit the emails by hand, because this is how things were managed usually in this company.&lt;/p&gt;

&lt;p&gt;I thought about releasing that on the CPAN in the &lt;code&gt;Mojolicious::Pugin::*&lt;/code&gt; namespace, but I had difficulties evaluating if it was a useful thing, really. &lt;/p&gt;

&lt;p&gt;Hope you liked that and that it was not too spooky.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mojolicious/mojo/discussions/1653" rel="noopener noreferrer"&gt;Initial thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://get.foundation/emails.html" rel="noopener noreferrer"&gt;Foundation Emails&lt;/a&gt;, a toolkit for generating emails from templates&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>perl</category>
      <category>outlook</category>
      <category>mojolicious</category>
    </item>
    <item>
      <title>Notes about the ongoing Perl logo discussion</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Sun, 09 Jul 2023 12:25:01 +0000</pubDate>
      <link>https://dev.to/smonff/notes-about-the-ongoing-perl-logo-discussion-4c80</link>
      <guid>https://dev.to/smonff/notes-about-the-ongoing-perl-logo-discussion-4c80</guid>
      <description>&lt;p&gt;More talks popped up recently about the Perl logo topic. I feel involved into this subject because even if my activities today are mostly about Perl programming and systems maintenance, I am from an artistic background, including graphic design. I was also interested about &lt;a href="https://news.ycombinator.com/item?id=10331008" rel="noopener noreferrer"&gt;Camelia design talks in the past&lt;/a&gt; and the initial &lt;a href="https://raw.githubusercontent.com/perl6/mu/master/misc/camelia.txt" rel="noopener noreferrer"&gt;mascot “specifications”&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;A professional graphic designer should be involved in the core discussion around the Perl logo.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;They could be given the complex logo history, articles like those written by &lt;a href="https://dev.to/thibaultduponchelle/open-letter-to-tim-oreilly-to-free-the-perl-camel-k3i"&gt;Thibault Duponchelle&lt;/a&gt; or &lt;a href="http://neilb.org/2020/12/04/perl-and-camels.html" rel="noopener noreferrer"&gt;Neil Bowers&lt;/a&gt;, plus &lt;a href="https://duckduckgo.com/?q=perl+lang+logo+camel+raptor+onion+camelia&amp;amp;t=newext&amp;amp;atb=v358-1&amp;amp;iar=images&amp;amp;iax=images&amp;amp;ia=images" rel="noopener noreferrer"&gt;existing logo material&lt;/a&gt;. Involving a graphic designer, outside the Perl community, would allow getting a fresh and neutral eye on the situation and possibly solve some Camel / Raptor disputes (or understand better the meaning of getting a Raptor after a Camel, etc.). &lt;/p&gt;

&lt;p&gt;It could also avoid all kind of basic design mistakes. The "shadow" O'Reilly derived logo is &lt;em&gt;very detailed&lt;/em&gt;. Logos usually don't use such detail levels, because they need to be identified even on smaller sizes (e.g. a browser tab). Let's take a look at a couple of examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the Raptor used on &lt;a href="https://perldoc.perl.org/" rel="noopener noreferrer"&gt;perldoc.perl.org&lt;/a&gt; works well as a logo;&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://www.perlmonks.org/" rel="noopener noreferrer"&gt;cropped O'Reilly book camel head on Perl Monks&lt;/a&gt; doesn't work too well: it's impossible to identify an animal head;&lt;/li&gt;
&lt;li&gt;on &lt;a href="https://www.nntp.perl.org/" rel="noopener noreferrer"&gt;https://www.nntp.perl.org/&lt;/a&gt; a full sized camel attempt is quite conclusive, what is surprising at this size. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A realistic camel is super difficult to use as a logo basis because it is a long animal, has too many legs and fluffy details. It won't work well except if it is “stylized” and simplified. The O'Reilly camel was a book cover, not a logo: there is no way it can work just by resizing it. &lt;/p&gt;

&lt;p&gt;An amazing example is &lt;a href="https://ocaml.org/" rel="noopener noreferrer"&gt;Ocaml lang&lt;/a&gt; &lt;a href="https://upload.wikimedia.org/wikipedia/commons/f/ff/OCaml_Logo.svg" rel="noopener noreferrer"&gt;logo / mascot&lt;/a&gt;. It might be useful to talk with them to know what was the process behind this work. The About page camel head on Perl dot org header is also a pretty good example of simplification, but it's not a logo, just a friendly illustration, as the O'Reilly camel is. Another notable logo for this animal is the well known tobacco industry company, but don't get me started on that (“good” logo, though, if we look at the effectiveness of their marketing).&lt;/p&gt;

&lt;p&gt;Only shadowing the O'Reilly camel (or other base pictures) won't work: we don't want to have such detailed legs, also the tail is weird, etc. An important part of the original O'Reilly drawing spirit is the animal face, and gaze, something that would totally be lost in a shadowed version. Also, the way the camel walks, its body posture, is very significant. How can we keep all that in a simple, tiny drawing? &lt;/p&gt;

&lt;p&gt;I don't have an opinion about which animal should better be used. There are even Perl material with butterflies, they are nice, although they are even more confusing since Raku (hello Camelia, &lt;a href="https://www.nntp.perl.org/group/perl.perl6.language/2009/03/msg31263.html" rel="noopener noreferrer"&gt;best programming language mascot ever&lt;/a&gt;!). Camel is better known. Raptor is more modern and surely works better as a logo. But if the-same-artist-who-made-the-raptor would draw a camel, wouldn't it also work? For what reason a Raptor was chosen then: what is the history, the meaning under the choice?&lt;/p&gt;

&lt;p&gt;Looks like both a &lt;em&gt;very hard work&lt;/em&gt;, and a relativelly straightforward process for a professional graphic designer, especially considering the complex history and heritage. And keep in mind that when we speak of graphic design, everybody got an opinion, coming with their own taste, culture.  &lt;/p&gt;

</description>
      <category>perl</category>
      <category>design</category>
      <category>culture</category>
      <category>community</category>
    </item>
    <item>
      <title>Maximize Data::Printer strings length</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Tue, 27 Jun 2023 08:22:47 +0000</pubDate>
      <link>https://dev.to/smonff/maximize-dataprinter-string-output-3agi</link>
      <guid>https://dev.to/smonff/maximize-dataprinter-string-output-3agi</guid>
      <description>&lt;p&gt;The Perl data structures and objects pretty printer &lt;a href="https://metacpan.org/pod/Data::Printer" rel="noopener noreferrer"&gt;&lt;code&gt;Data::Printer&lt;/code&gt;&lt;/a&gt; would trim strings longer than &lt;code&gt;4096&lt;/code&gt; characters (this is the default value). &lt;/p&gt;

&lt;p&gt;This is something that can be parameterized in the &lt;code&gt;~/.dataprinter&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# No limit!
&lt;/span&gt;&lt;span class="n"&gt;string_max&lt;/span&gt;        = &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This default is sensible, though, because you usually don't want the program output to fill with too much text.&lt;/p&gt;

&lt;p&gt;It might be necessary to change this value, only in a specific place. You can pass a false value to &lt;code&gt;string_max&lt;/code&gt; to display the whole string fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;p&lt;/span&gt; &lt;span class="nv"&gt;$object_with_long_string_values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;string_max&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More information can be found in the &lt;a href="https://metacpan.org/pod/Data::Printer#CUSTOMIZATION" rel="noopener noreferrer"&gt;module &lt;em&gt;Customization&lt;/em&gt; section&lt;/a&gt;, along with all the available configuration parameters.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>debugging</category>
      <category>dumper</category>
      <category>dataprinter</category>
    </item>
    <item>
      <title>Why am I giving up on Perl? (edit: I didn't)</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Mon, 02 Aug 2021 20:46:42 +0000</pubDate>
      <link>https://dev.to/smonff/why-am-i-giving-up-on-perl-4ni6</link>
      <guid>https://dev.to/smonff/why-am-i-giving-up-on-perl-4ni6</guid>
      <description>&lt;p&gt;I started using Perl in 2010. After years of a passionate use, I start to plan something else. Disclaimer: this is not because of &lt;em&gt;"the language"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: at the end of August, after the publication of this post, some very &lt;del&gt;helpful&lt;/del&gt; lovely persons came to me and the situation changed quite a bit. More on this later...&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It is a real career issue
&lt;/h2&gt;

&lt;p&gt;In my country of living, getting a Perl job is a real problem. I worked the last four years in a small team where all the projects were done using Perl and Mojolicious. As far as I know, even if I got fired for economic reasons linked to pandemic situation, all the applications I deployed there are still working well despite they are not maintained anymore (ouch).&lt;/p&gt;

&lt;p&gt;Then, what I saw since March on the jobs market is: there is a niche of companies or organizations that still do an active use of Perl. What I notice is that they are all thinking of switching to other platform (maybe they are right, after all this is something that seem to go on since 15 years), and that there is no way new projects are developed with Perl. What I felt by talking with a CTO is that she hadn't any more trust with Perl: she was not able to recruit people. Therefore, they are hiding the Perl aspect in the jobs offers and then have even more difficulties finding people. Then, when they find some persons, they would even decide that, maybe, they should hire someone more versatile. And that person will be sad, maintaining some Perl, can you imagine this hell?&lt;/p&gt;

&lt;p&gt;I mean, this is a kind of very sad waste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;help&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I missed two opportunities based on the fact that I was not a polyglot enough. I know Java, JavaScript, Perl, quite enough of various web technologies like HTML and CSS, but still, I don't know something like Go, Python, you know this stuff is real trendy! I don't value the idea of &lt;em&gt;polyglotism&lt;/em&gt; a lot, because I prefer to focus on something, and also, I am not really able to learn a lot of programming languages. I know this is not a very popular opinion, and now I feel like in trouble. So I'll try to improve myself.&lt;/p&gt;

&lt;p&gt;It would still be possible to switch to Raku. This is a fantastic language, and I would really like to involve myself into it, but seriously, I need to pay my bills. I mean, the probability to find a Raku job in my country is... Small?&lt;/p&gt;

&lt;h2&gt;
  
  
  Lack of gender equality and diversity in the communities
&lt;/h2&gt;

&lt;p&gt;The Perl communities are dominated by mostly men. There are rare persons who advocate for diversity and inclusivity, but honestly, if it exists at some conferences, it is not what is spread by the communities: just check the stats of Perl Weekly contributors or other popular Perl cultural items, this is the same-old men-leaded-content everywhere with very little exceptions.&lt;/p&gt;

&lt;p&gt;If I decide to go away from this community, I will at least contribute to reduce the gender gap. Plus, it will be one grumpy person less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recent communities issues are awfully worrying
&lt;/h2&gt;

&lt;p&gt;Perl has a number of toxic community members, this is not new. They are armful to other, and I got very shocked of some events that happened recently. I'll focus here exclusively on the victims.&lt;/p&gt;

&lt;p&gt;Sawyer X, &lt;em&gt;pumpkin&lt;/em&gt; of Perl since 2016 resigned of their responsibilities after being &lt;a href="https://www.theregister.com/2021/04/13/perl_dev_quits/" rel="noopener noreferrer"&gt;victim of harassment&lt;/a&gt;. It is unacceptable that a person enduring such responsibilities are bullied by communities members.  &lt;/p&gt;

&lt;p&gt;Wendy totally vanished of the Perl communities after years of active quality work for the advocacy of Perl. I am totally sure I would have never been interested in Perl that much without Wendy. She encouraged me, her talks and the way she was engaged marked me forever. She gave me a &lt;em&gt;Learning Perl&lt;/em&gt; book copy, and sent me to Curtis Ovid Poe to ask for a signature. Meeting her was a major event in my Perl career, and I made a very good use of this gift. From what I understood, it was partly the Raku renaming that took her away, but I suppose it is more the talks and difficult interactions that happened at this time. I don't know where you are now, Wendy, and how you are doing, but I wanted to thank you.&lt;/p&gt;

&lt;p&gt;The Mojolicious community recently denounced a racist issue in a CPAN distribution to TPF, and after it didn't get answered accurately, pointed a conflict of interest inside TPF itself. Result: nothing. &lt;/p&gt;

&lt;p&gt;All those, and the lack of reactions from the communities members, continuing to do their release and challenges and blog posts as if everything was going fine, all of this made me sick. And you know what? I don't even want to participate in this a lot, even if I will always love the language in itself and have a good memory of my time around Perl, and it's communities. I guess I have been marked by a very small amount of personalities, that inspired me a lot of love and motivation, but what I am seeing right now, this is not where I want to be. &lt;/p&gt;

&lt;h2&gt;
  
  
  Modern Perl, Perl7, Corinna
&lt;/h2&gt;

&lt;p&gt;All this is very exciting, seriously, I mean it. When the Perl7 announcement came, I felt really, something will be going to happen. Then I saw all the discourse and the doubt it created, and I got afraid.&lt;/p&gt;

&lt;p&gt;In 2021, I feel like that there are a lot of codebases that still didn't incorporate the Modern Perl ideas. It's rare to see usages of subroutines signatures, even if the feature is (experimentally) around since 2015.&lt;/p&gt;

&lt;p&gt;Corinna, and its possible implementation, &lt;a href="https://metacpan.org/pod/Object::Pad" rel="noopener noreferrer"&gt;Object::Pad&lt;/a&gt; looks to progress real well, and I am almost sure it will be usable soon.&lt;/p&gt;

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

&lt;p&gt;But still, I am not patient enough, and I need to get a job: unfortunately, it looks like managers and CTOs lost the confidence in Perl, and that Perl codebases should be only fixed: new code should be written in other languages. Again, this is only what I saw in France, maybe it is different in other countries, and this is not what I wish, since I have been a Perl enthusiast since 2010, and wrote new web applications 100% with Perl in the 4 last years. I wish I could find more context for this incomprehensible Perl love, but for the above reasons, I'll have to go search somewhere else. It must be &lt;a href="https://dev.to/smonff/i-started-studying-python3-2pga"&gt;a good decision&lt;/a&gt;, I guess...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;antigravity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: I received lots of support and advices after posting this. I am grateful to the people who helped me.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>community</category>
      <category>toxicity</category>
      <category>career</category>
    </item>
    <item>
      <title>I started studying Python3</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Mon, 02 Aug 2021 20:05:08 +0000</pubDate>
      <link>https://dev.to/smonff/i-started-studying-python3-2pga</link>
      <guid>https://dev.to/smonff/i-started-studying-python3-2pga</guid>
      <description>&lt;p&gt;I am encountering employment difficulties with Perl lately, so I decided to cross the gap. A &lt;a href="https://dev.to/smonff/why-am-i-giving-up-on-perl-4ni6"&gt;&lt;em&gt;"reasons why"&lt;/em&gt; post is also available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I started less than one week ago, so coding is still a bit hard: I am mostly evaluating expressions in the repl, I use &lt;a href="https://bpython-interpreter.org/" rel="noopener noreferrer"&gt;&lt;code&gt;bpython&lt;/code&gt;&lt;/a&gt; and feel extremely satisfied with it.&lt;/p&gt;

&lt;p&gt;For now, the feeling is smooth and I am quite happy: everything I am used to in Perl can be found in Python. I see no major differences between the two languages. I am a bit surprised how sometimes the Python core have batteries included, you don't necessarily need to install modules. The only thing I miss is Mojolicious, I mean, I know there are similar tools, but I have habits, and they should simply evolve.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reading
&lt;/h1&gt;

&lt;p&gt;So far I am reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/3.2/intro/" rel="noopener noreferrer"&gt;&lt;em&gt;The Django Tutorial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/tutorial/index.html" rel="noopener noreferrer"&gt;&lt;em&gt;The Python tutorial&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://effectivepython.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Effective Python&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Planning to read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.manning.com/books/the-quick-python-book-third-edition" rel="noopener noreferrer"&gt;&lt;em&gt;The Quick Python Book&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Language
&lt;/h1&gt;

&lt;p&gt;Relatively to the language itself here are few things I noticed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;absence of sigils (&lt;code&gt;@those %things $you *know&lt;/code&gt;): I really dislike it, it makes code less readable in my opinion. I would be tempted to systematically use &lt;code&gt;two_words&lt;/code&gt; syntax for variables. With sigils, you target easier what is a variable or what is a keyword. Maybe I am too much used to Perl and that on the long term, this is really a minor issue, especially that functions require parenthesis with Python3, you can’t write &lt;code&gt;print 'perl is cute'&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;functions require parenthesis. It’s a lot of parenthesis typing, I guess my text editor is not configured the right way&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Modules
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;I miss &lt;a href="https://metacpan.org/pod/Data::Printer" rel="noopener noreferrer"&gt;&lt;code&gt;Data::Printer&lt;/code&gt;&lt;/a&gt;, one of my favorite Perl debugging tools ever. I install it everywhere, even for the simplest project. I searched for equivalents, but none of the one that I found, like &lt;a href="https://pypi.org/project/data-printer/" rel="noopener noreferrer"&gt;&lt;code&gt;data_printer&lt;/code&gt;&lt;/a&gt; (directly inspired from the Perl implementation) or &lt;a href="https://github.com/gaogaotiantian/objprint" rel="noopener noreferrer"&gt;&lt;code&gt;objprint&lt;/code&gt;&lt;/a&gt; are as simple to use out-of-the-box than &lt;code&gt;Data::Printer&lt;/code&gt;, that also have a better display&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>education</category>
    </item>
    <item>
      <title>I’ll attend the Perl and Raku Conference In the Cloud</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Wed, 09 Jun 2021 13:53:27 +0000</pubDate>
      <link>https://dev.to/smonff/i-ll-attend-the-perl-conference-in-the-cloud-jlh</link>
      <guid>https://dev.to/smonff/i-ll-attend-the-perl-conference-in-the-cloud-jlh</guid>
      <description>&lt;p&gt;This year, I am unemployed so let’s try to attend and follow the &lt;a href="https://perlconference.us/tprc-2021-cloud/" rel="noopener noreferrer"&gt;Perl and Raku Conference In the Cloud&lt;/a&gt;. Feeling quite bored since those days, I am not too much into computer stuff but more like gardening, fixing my house, take care of my cat,  cooking and do wood work, but let’s try.&lt;/p&gt;

&lt;p&gt;I bought a ticket.&lt;/p&gt;

</description>
      <category>conference</category>
      <category>yapc</category>
      <category>tprc</category>
      <category>perl</category>
    </item>
    <item>
      <title>True private attributes and methods for modern Perl OOP</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Sat, 20 Mar 2021 14:58:59 +0000</pubDate>
      <link>https://dev.to/smonff/true-private-attributes-and-methods-for-modern-perl-oop-2i39</link>
      <guid>https://dev.to/smonff/true-private-attributes-and-methods-for-modern-perl-oop-2i39</guid>
      <description>&lt;p&gt;Today we will &lt;a href="https://dev.to/smonff/random-integer-generation-in-an-interval-with-modern-oop-perl-4p2c"&gt;continue&lt;/a&gt; our exploration of modern Perl OOP. Those are very experimental features, but I feel like it could be a bit similar to what &lt;a href="https://github.com/Ovid/Cor" rel="noopener noreferrer"&gt;Corinna&lt;/a&gt; could look like so I find it fun to try new things. This is also an opportunity to learn more about OOP.&lt;/p&gt;

&lt;p&gt;This is an example of how to implement private attributes and methods with the &lt;a href="https://zydeco.toby.ink/" rel="noopener noreferrer"&gt;Zydeco&lt;/a&gt; toolkit. We will also see how polymorphism and named parameters works for the needs of this example.&lt;/p&gt;

&lt;p&gt;There are other OO modules plugins that allow to add privacy features, but in Perl, it is interesting to see that, privacy is often mostly by convention: subroutines are prefixed with an underscore (e.g. &lt;code&gt;sub _super_private { ... }&lt;/code&gt;) and everybody will consider it as private. See &lt;a href="https://perlmaven.com/moo-with-public-and-private-methods" rel="noopener noreferrer"&gt;a short explanation about this on perlmaven.com&lt;/a&gt; in the &lt;em&gt;Public and private methods&lt;/em&gt; section.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;DevTo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Zydeco&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Privacy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;# Predeclaration of the accessor coderef&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$hidden_attr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;wonder&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;hidden&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;accessor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$hidden_attr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;$innaccessible_method&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No problem acessing &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;wonder&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; through a private method&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;$innaccessible_method_attr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$hidden_attr&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;a hidden place&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
      &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No problem accessing a private attribute in &lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$hidden_attr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;multi&lt;/span&gt; &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;no_problem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$innaccessible_method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;multi&lt;/span&gt; &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;Bool&lt;/span&gt; &lt;span class="nv"&gt;*with_attr&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$innaccessible_method_attr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$access&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;DevTo&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;new_privacy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;wonder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a public attribute&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nv"&gt;$access&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;# ==&amp;gt; "No problem acessing a public attribute through a private method"&lt;/span&gt;
  &lt;span class="nv"&gt;$access&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s"&gt;with_attr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;# ==&amp;gt; "No problem accessing a private attribute in a hidden place"&lt;/span&gt;

  &lt;span class="c1"&gt;# This would fail&lt;/span&gt;
  &lt;span class="c1"&gt;# $access-&amp;gt;$innaccessible_method;&lt;/span&gt;

  &lt;span class="c1"&gt;# No things are not possible&lt;/span&gt;
  &lt;span class="c1"&gt;# $access-&amp;gt;hidden_attr;&lt;/span&gt;
  &lt;span class="c1"&gt;# $access-&amp;gt;$hidden_attr;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what are we doing here?&lt;/p&gt;

&lt;p&gt;The privacy with Zydeco can target two different entities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attributes, by using the &lt;code&gt;is =&amp;gt; private&lt;/code&gt; during the attribute declaration&lt;/li&gt;
&lt;li&gt;methods, by prefixing the method name with a &lt;code&gt;$&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have two private methods, that we will call from the public &lt;em&gt;multi&lt;/em&gt; &lt;code&gt;no_problem()&lt;/code&gt; method. This one is declared two times, with different signatures and prefixed with the &lt;code&gt;multi&lt;/code&gt; keyword: it makes possible to setup the polymorphism, dispatching the desired behavior depending on the passing of a boolean or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Would call $inaccessible_method&lt;/span&gt;
&lt;span class="nv"&gt;$access&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;# Would call $inaccessible_method_attr&lt;/span&gt;
&lt;span class="nv"&gt;$access&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s"&gt;with_attr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how &lt;em&gt;named attributes&lt;/em&gt; are declared and easily used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;multi&lt;/span&gt; &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;no_problem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;Bool&lt;/span&gt; &lt;span class="nv"&gt;*with_attr&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By prefixing the parameter name with a &lt;code&gt;*&lt;/code&gt; and not a &lt;code&gt;$&lt;/code&gt; in the method signature, you get automatic parameter names ready for later &lt;/p&gt;

&lt;p&gt;Then, we create a new &lt;code&gt;Privacy&lt;/code&gt; object that we call &lt;code&gt;$access&lt;/code&gt;. &lt;code&gt;Privacy&lt;/code&gt; got a public attribute, &lt;code&gt;wonder&lt;/code&gt; and one that is private, called &lt;code&gt;hidden&lt;/code&gt;. With Zydeco, declaring an attribute as "private" &lt;a href="https://zydeco.toby.ink/02_Attributes.html#Declaring_a_Basic_Attribute" rel="noopener noreferrer"&gt;make it assessor-less&lt;/a&gt;. Under the hood, if you check on of the underlying technologies that power Zydeco, it &lt;a href="https://metacpan.org/pod/MooX::Press#Attribute-Specifications" rel="noopener noreferrer"&gt;doesn't mean that the attribute is totally inaccessible&lt;/a&gt;: we &lt;em&gt;can request an accessor as a coderef&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$hidden_attr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;hidden&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;accessor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$hidden_attr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then access the attribute &lt;em&gt;in the scope of the variable&lt;/em&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;$access&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$hidden_attr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outside the variable scope, the attribute will be totally invisible. This is possible thanks to a &lt;a href="https://stackoverflow.com/questions/7814489/how-do-you-dynamically-call-a-method-of-an-object" rel="noopener noreferrer"&gt;handy technic&lt;/a&gt; that allows to call methods dynamically.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://zydeco.toby.ink" rel="noopener noreferrer"&gt;https://zydeco.toby.ink&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://perlmaven.com/moo-with-public-and-private-methods" rel="noopener noreferrer"&gt;https://perlmaven.com/moo-with-public-and-private-methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metacpan.org/pod/MooX::Press#Attribute-Specifications" rel="noopener noreferrer"&gt;https://metacpan.org/pod/MooX::Press#Attribute-Specifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>oop</category>
      <category>zydeco</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Random integer generation in an interval with Modern OOP Perl</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Tue, 23 Feb 2021 11:45:18 +0000</pubDate>
      <link>https://dev.to/smonff/random-integer-generation-in-an-interval-with-modern-oop-perl-4p2c</link>
      <guid>https://dev.to/smonff/random-integer-generation-in-an-interval-with-modern-oop-perl-4p2c</guid>
      <description>&lt;p&gt;I always have to search &lt;a href="https://stackoverflow.com/a/21806398/954777" rel="noopener noreferrer"&gt;how to generate a random integer number between a range&lt;/a&gt; because this is a common task that I use a lot in tests, but really, I can't memorize it.&lt;/p&gt;

&lt;p&gt;Though, this is how I would do it in 2021.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;# Class definition&lt;/span&gt;
&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;Random::&lt;/span&gt;&lt;span class="nv"&gt;Range&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Zydeco&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;pick&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt; &lt;span class="nv"&gt;$min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Int&lt;/span&gt; &lt;span class="nv"&gt;$max&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$min&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$min&lt;/span&gt; &lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Script&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nn"&gt;Random::&lt;/span&gt;&lt;span class="nv"&gt;Range&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;new_integer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;#==&amp;gt; 42 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what did we do here? We used the &lt;a href="https://perldoc.pl/functions/rand" rel="noopener noreferrer"&gt;&lt;code&gt;rand&lt;/code&gt;&lt;/a&gt; function where we applied the &lt;code&gt;int&lt;/code&gt; function, so we would get an integer, not a fractional number. The small calculation makes possible to restrict the result to the desired interval.&lt;/p&gt;

&lt;p&gt;All of this is glued into a minimal Zydeco class that adds a very nice object-oriented interface. You maybe don't need Zydeco, this simple one-liner would work:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;perl -le 'my @interval = (1, 100); print $interval[0] + int ( rand ( $interval[1] - $interval[0] ))'  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note this is not cryptographically secure and should only be used in simple cases: if you need a secure implementation, please check some &lt;a href="https://metacpan.org/search?q=math+random+secure" rel="noopener noreferrer"&gt;appropriate solutions on CPAN&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Art: digital painting by myself.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>oop</category>
      <category>random</category>
    </item>
    <item>
      <title>Load a list of lines into an array (easily)</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Tue, 13 Oct 2020 14:42:35 +0000</pubDate>
      <link>https://dev.to/smonff/load-a-list-of-lines-into-an-array-for-processing-them-in-perl-412a</link>
      <guid>https://dev.to/smonff/load-a-list-of-lines-into-an-array-for-processing-them-in-perl-412a</guid>
      <description>&lt;p&gt;This blog post describes a common task my colleagues ask often about repeating a dynamic string in a defined token and adding some &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt; in between, plus finishing smartly.&lt;/p&gt;

&lt;p&gt;I like to use the Perl's &lt;code&gt;__DATA__&lt;/code&gt; token at the end of my scripts for this. The &lt;code&gt;__DATA__&lt;/code&gt; token strength is to make possible to &lt;a href="https://www.perl.com/article/stupid-data-tricks/" rel="noopener noreferrer"&gt;&lt;em&gt;« "embed” a file inside a Perl program then read it from the DATA filehandle »&lt;/em&gt;&lt;/a&gt;. It saves you the creation and opening of a real file and is very handy for quick prototypes and tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env perl&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# Your script here&lt;/span&gt;

&lt;span class="c1"&gt;# Everything under is considered as &lt;/span&gt;
&lt;span class="c1"&gt;# the end of the code&lt;/span&gt;
&lt;span class="cp"&gt;__DATA__
a
lot
lot
of
stuff
here
...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common practice is to load those data to an array by treating them as a file handle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the values would include carriage returns, what you obviously don't want. I used two solutions for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is quite readable and self-explanatory (remember Perl a natural language, it was created by a linguist). Feel free to comment if something is unclear so I could improve the post.&lt;/p&gt;

&lt;p&gt;Ok, I have to admit a little secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... without the pre-declaration of &lt;code&gt;@lines&lt;/code&gt; does the same. I had to counter check it worked, but as often with Perl, when you spontaneously think of something silly, it actually works naturally (I have to admit it sometimes looks like a miracle).&lt;/p&gt;

&lt;p&gt;If you want &lt;code&gt;uniq&lt;/code&gt; values (you surely do), one way is to  use the core module &lt;code&gt;List ::Util&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nv"&gt;uniq&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it" rel="noopener noreferrer"&gt;Another way to do it&lt;/a&gt; is always possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;uniq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I actually prefer this &lt;em&gt;list context&lt;/em&gt; solution, for it's shortness, dunno which one is the more readable, and it is good to choose the readable way. &lt;/p&gt;

&lt;p&gt;Let's say you want to generate a series of &lt;code&gt;or&lt;/code&gt; for your colleagues or customers. We are actually doing a super advanced language generation thing here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env perl&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;List::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="sx"&gt;qw(uniq)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;uniq&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# $_ is the current loop element&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nv"&gt;generate_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;# $lines[-1] is the last array element&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;$lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; or &lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;    

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;generate_string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line == "&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;__DATA__
a
lot
lot
of
stuff
here
...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ perl lines.pl
line == "a' or line == "lot' or line == "of' or line == "stuff' or line == "here' or line == "...'  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lots of other solutions exist, check the &lt;a href="https://raw.githubusercontent.com/pkrumins/perl1line.txt/master/perl1line.txt" rel="noopener noreferrer"&gt;&lt;em&gt;Perl one-liners&lt;/em&gt;&lt;/a&gt; thing that allow to learn a lot more about those kind of practices.&lt;/p&gt;

&lt;p&gt;The quantities of cools things you can do inside this loop is infinite, from log parsing to generating code or data munging, thanks to the kindness of Perl. &lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/5948360/read-a-file-into-an-array-using-perl" rel="noopener noreferrer"&gt;Read a file into an array using Perl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.perl.com/article/stupid-data-tricks/" rel="noopener noreferrer"&gt;Silly DATA Tricks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Note
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I wrote this because my memory is awful and I was tired of always searching for the exact syntax of the &lt;code&gt;__data__&lt;/code&gt; token to array process. Hope it will help all kinds of people including me when I type it in a search engine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>perl</category>
      <category>array</category>
      <category>line</category>
      <category>datamunging</category>
    </item>
    <item>
      <title>A concise mtime sorted directory listing application</title>
      <dc:creator>🌌 Sébastien Feugère ☔</dc:creator>
      <pubDate>Tue, 18 Feb 2020 19:10:16 +0000</pubDate>
      <link>https://dev.to/smonff/a-concise-mtime-sorted-directory-listing-application-3dcd</link>
      <guid>https://dev.to/smonff/a-concise-mtime-sorted-directory-listing-application-3dcd</guid>
      <description>&lt;p&gt;Today we will focus on a simple task: listing the files contained in a directory, sort them by modification time (&lt;a href="https://en.wikipedia.org/wiki/Stat_(system_call)#ctime" rel="noopener noreferrer"&gt;&lt;code&gt;mtime&lt;/code&gt;&lt;/a&gt;) and display the result in a JSON array.&lt;/p&gt;

&lt;p&gt;We are gonna use &lt;a href="https://mojolicious.org/perldoc/Mojo/File" rel="noopener noreferrer"&gt;&lt;code&gt;Mojo::File&lt;/code&gt;&lt;/a&gt; for the file system part and &lt;a href="https://mojolicious.org/perldoc/Mojolicious/Lite" rel="noopener noreferrer"&gt;&lt;code&gt;Mojolicious::Lite&lt;/code&gt;&lt;/a&gt; to expose those data on a simple but effective JSON API. &lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libmojolicious-perl

&lt;span class="nb"&gt;touch &lt;/span&gt;mtime.pl &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; +x mtime.pl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The code
&lt;/h1&gt;

&lt;p&gt;Our lite application is separated in two main parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Tutorial#toc" rel="noopener noreferrer"&gt;&lt;em&gt;helper&lt;/em&gt;&lt;/a&gt;, the &lt;code&gt;get_paths_by_ctime()&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;an unique &lt;a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Tutorial#toc" rel="noopener noreferrer"&gt;&lt;em&gt;route&lt;/em&gt;&lt;/a&gt; that returns an array reference containing our file list
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env perl&lt;/span&gt;

&lt;span class="c1"&gt;# Automagically import Mojo::Base -base&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojolicious::&lt;/span&gt;&lt;span class="nv"&gt;Lite&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;signatures&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Mojo::&lt;/span&gt;&lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

&lt;span class="nv"&gt;helper&lt;/span&gt; &lt;span class="s"&gt;get_paths_by_mtime&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$files_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tmp&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Returns an array of Mojo::File&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$files_list&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;each&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;# Returns an array of paths sorted by modification date&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;realpath&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;to_string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nv"&gt;get&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get_paths_by_mtime&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Starting the app
&lt;/h1&gt;

&lt;p&gt;Mojolicious comes with the &lt;code&gt;morbo&lt;/code&gt; HTTP and WebSocket development server&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;morbo mtime.pl
Server available at http://127.0.0.1:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you visit this adress in your browser, it should display the list of files contained in the &lt;code&gt;/tmp&lt;/code&gt; directory of your computer. On mine it returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/sddm-:0-RweLaZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/xauth-1000-_0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/cpan_install_3QQI.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!.emacs.d!savefile!ido.hist~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!.emacs.d!savefile!recentf~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!dev!processing-perl!etc!crontab~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!.emacs.d!personal!custom.el~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!dev!processing!.env~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/liste_desabonnement_20200218.csv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!dev!processing!.git!COMMIT_EDITMSG~"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"/tmp/!home!sfeu!scripts!mtime.pl~"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is just a bunch of temporary files, mostly those I edit in my text editor. Note that the directories and special files (&lt;code&gt;.&lt;/code&gt;, &lt;code&gt;..&lt;/code&gt;) are not listed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Releasing the power of &lt;code&gt;Mojo::File&lt;/code&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Retrieving a list of files
&lt;/h2&gt;

&lt;p&gt;Mojolicious provide a lot of utilities that makes your Perl programmer life almost bearable. Note that Mojolicious needs zero dependencies, this is the reason it comes with a great toolkit for doing simple tasks. &lt;a href="https://mojolicious.org/perldoc/Mojo/File" rel="noopener noreferrer"&gt;&lt;code&gt;Mojo::File&lt;/code&gt;&lt;/a&gt; is one of those. Let's see how to use it.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;By &lt;em&gt;using&lt;/em&gt; &lt;code&gt;Mojo::File&lt;/code&gt; and loading it's &lt;em&gt;path&lt;/em&gt; function, you will be able to &lt;em&gt;construct a &lt;code&gt;Mojo::File&lt;/code&gt; object&lt;/em&gt; by passing it any kind of path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$files_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tmp&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;list&lt;/code&gt; method called on a &lt;code&gt;Mojo::File&lt;/code&gt; directory will return all files contained in this directory. The returned object is a &lt;a href="https://mojolicious.org/perldoc/Mojo/Collection" rel="noopener noreferrer"&gt;&lt;code&gt;Mojo::Collection&lt;/code&gt;&lt;/a&gt; object, an &lt;em&gt;array-based container for collections&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sorting the objects by modification date
&lt;/h2&gt;

&lt;p&gt;To read the following code, start by the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$files_list&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;each&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;first, you return all the elements of the collection by using &lt;code&gt;each&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;it will return an array, that can be passed to &lt;a href="https://perldoc.pl/functions/sort" rel="noopener noreferrer"&gt;&lt;code&gt;sort&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;sort&lt;/code&gt; is being passed a comparison function. In our case we will compare by &lt;code&gt;mtime&lt;/code&gt; (modification time). The reason we can access to &lt;code&gt;mtime&lt;/code&gt; from the array of &lt;code&gt;Mojo::File&lt;/code&gt;s is that this module got it's own &lt;a href="https://mojolicious.org/perldoc/Mojo/File#stat" rel="noopener noreferrer"&gt;&lt;code&gt;stat&lt;/code&gt; method&lt;/a&gt; that returns itself &lt;em&gt;a &lt;a href="https://mojolicious.org/perldoc/File/stat" rel="noopener noreferrer"&gt;&lt;code&gt;File::stat&lt;/code&gt;&lt;/a&gt; object for the path&lt;/em&gt;. This is where the magic happend!&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieving the files paths
&lt;/h2&gt;

&lt;p&gt;By using a simple &lt;code&gt;map&lt;/code&gt; function and the &lt;code&gt;Mojo::File&lt;/code&gt; chained&lt;code&gt;realpath-&amp;gt;to_string&lt;/code&gt; methods we will transform our array of objects to a simple array of strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;realpath&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;to_string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The route
&lt;/h1&gt;

&lt;p&gt;The result of our helper is then &lt;em&gt;rendered&lt;/em&gt; as JSON (must be passed to the front as an &lt;code&gt;arrayref&lt;/code&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Making it even more concise
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://marcus.nordaaker.com/about" rel="noopener noreferrer"&gt;Marcus Ramberg&lt;/a&gt; explained me how to make this even more concise by using &lt;a href="https://mojolicious.org/perldoc/Mojo/Collection#sort" rel="noopener noreferrer"&gt;&lt;code&gt;Mojo::Collection-&amp;gt;sort&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The helper can be rewritten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;helper&lt;/span&gt; &lt;span class="s"&gt;get_paths_by_mtime&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tmp&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;mtime&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The conciseness and readability of this program is quite surprising thanks to the effective tools used. &lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading this presentation and that it gave you the wish to use the &lt;em&gt;formidable&lt;/em&gt; Mojolicious framework and it's utilities.&lt;/p&gt;

&lt;h1&gt;
  
  
  Acknowledgments
&lt;/h1&gt;

&lt;p&gt;Thanks to Marcus Ramberg who read this, improved and simplified the code.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>mojolicious</category>
      <category>listing</category>
      <category>mtime</category>
    </item>
  </channel>
</rss>
