<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="atom.css"  ?>


<feed xmlns="http://www.w3.org/2005/Atom">

    <title>alastair.pl</title>
    <subtitle>untitled documents</subtitle>
    <link href="https://alastair.pl/feed" rel="self" />
    <link href="https://alastair.pl/feed" />
    <id>https://alastair.pl/feed</id>
    <updated>2024-02-01T12:55:44Z</updated>
    

    <entry>
        <title>Stick a secret url in a qr code</title>
<link href="https://alastair.pl/2024/02/01/Stick-a-secret-url-in-a-qr-code" />
        <link href="https://alastair.pl/2024/02/01/Stick-a-secret-url-in-a-qr-code.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2024/02/01/Stick-a-secret-url-in-a-qr-code.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2024/02/01/Stick-a-secret-url-in-a-qr-code</id>
        <updated>2024-02-01T12:55:44Z</updated>
        <summary> </summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
<p>There are a couple of qr code libraries on cpan, but I stopped looking when the first one worked:</p>

<p><code class="language-perl">cpanfile</code>:</p>

<pre><code class="language-perl">requires 'Image::PNG::QRCode', '0.10';
requires 'Mojolicious', '9.35';
</code></pre>

<p><code class="language-perl">$ carton install</code></p>

<p><code class="language-perl">qrthing</code>:</p>

<pre><code class="language-perl">#!perl

use Mojolicious::Lite -signatures;
use Image::PNG::QRCode 'qrpng';
use Mojo::Util 'b64_encode';

get '/' =&gt; sub ($c)  {
    my $blob  = qrpng(text =&gt; $c-&gt;url_for('sekrit', {code =&gt; 1234})-&gt;to_abs);
    $c-&gt;stash(template =&gt; 'index', 'img' =&gt; b64_encode $blob)
};

get '/sekrit/:code' =&gt; sub ($c) {
    $c-&gt;render(text =&gt; 'secret area');
}, 'sekrit';

app-&gt;start

__DATA__

@@ index.html.ep

Scan me: 
&lt;img src="data:image/png;base64,&lt;%= $img %&gt;"&gt;
</code></pre>

<p>We can fire up the webserver the regular mojo way:</p>

<p><code class="language-perl">
$ carton exec -- local/bin/hypnotoad ./qrthing
</code></p>

<p>We've all seen a qr code before, so i think it's Ok to skip the screen shot...</p>

<h1 id="thatsit">That's it</h1>

<p>I just think it's neat. </p>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="Perl5" />

    </entry>
    <entry>
        <title>I like that perl has stuff like ...</title>
<link href="https://alastair.pl/2023/03/11/I-like-that-perl-has-stuff-like-" />
        <link href="https://alastair.pl/2023/03/11/I-like-that-perl-has-stuff-like-.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2023/03/11/I-like-that-perl-has-stuff-like-.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2023/03/11/I-like-that-perl-has-stuff-like-</id>
        <updated>2023-03-11T12:55:44Z</updated>
        <summary>... is more powerful than anyone could imagine</summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
<p><code class="language-perl">...</code> is a 3-in-one power house</p>

<h1 id="ilikethatperlhasstufflike...">I like that perl has stuff like <code class="language-perl">...</code></h1>

<p><code class="language-perl">..</code> goes by many names, but it is actually 3 fairly neat things. 
<a href="https://perldoc.perl.org/perlop#Range-Operators">perldoc</a></p>

<h2 id="yada-yada-aplaceholderforunimplementedcode.">yada-yada - a placeholder for unimplemented code.</h2>

<p>In void context <code class="language-perl">...</code> is the "yada yada". It is fatal and dies with "unimplemented". </p>

<p>You can use this while planning out a module. You can quickly throw down a</p>

<pre><code class="language-perl">sub write_me_later { ... }
</code></pre>

<p>... and when you call it (say from your tests) <code class="language-perl">perl</code> will remind you that you haven't written that sub yet. </p>

<h2 id="aflipflop-withsetreset">A flip flop - with set/reset!</h2>

<p>In scalar context it returns true after the thing on the left is true, until the thing on the right becomes true. </p>

<p>This is the set/reset behaviour of a "flip flop", and it is really helpful when parsing lines of a file.</p>

<pre><code class="language-perl">while(&lt;&gt;) {
    if (/flip/.../flop/) {
        # every line between a flip and a flop (including the lines that do)
        say "flipped: $_"
    }
}
</code></pre>

<p>Simply <code class="language-perl">/start-of-range/../end-of-range/</code> is true between those two matches.</p>

<h2 id="ranges-tradetwonumbersformany">Ranges - trade two numbers for many!</h2>

<p>Unsurprisingly in list context <code class="language-perl">...</code> gives a list, it works with similar rules to <code class="language-perl">++</code>, so:
- <code class="language-perl">1..10</code> gives you back the numbers you expect. 
- <code class="language-perl">"OWF1".."OWF9"</code> gives you back a list that includes <code class="language-perl">"OWF6"</code></p>

<p>It's particularly handy for avoiding off-by-one's when looping over arrays:</p>

<pre><code class="language-perl">for (0..$#array) { # No &lt; @array... or is it &lt;= @array?
    printf "I'm at index %s, which is: %s\n", $_, $array[$_] 
}
</code></pre>

<h2 id="itallcomesfromcontext">It all comes from context</h2>

<p>I think it's very cool that 2 or 3 characters can do all of these things, and that their meaning comes entirely from the context.</p>

<h2 id="thatsit.">That's it.</h2>

<p>I just think that's neat.</p>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="Why I like perl" />
        <category term="Programming" />

    </entry>
    <entry>
        <title>I&#39;ll fix it later</title>
<link href="https://alastair.pl/2022/11/23/later" />
        <link href="https://alastair.pl/2022/11/23/later.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2022/11/23/later.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2022/11/23/later</id>
        <updated>2022-11-23T12:55:44Z</updated>
        <summary>Sure, bud </summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
<p><style type="text/css">.proof-post-icon { float:left;padding-right:1em; }</style></p>

<p><img src="data:image/jpeg;base64,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" alt="proof-post-icon" id="proof-post-icon" /></p>

<p>Come on man, it's an emergency, and we need to fix this right away, so ...</p>

<h1 id="illfixitlater">"I'll fix it later"</h1>

<p>I mean far be it from me to suggest that you're making that up.</p>

<p>I believe we should give people the benifit of the doubt. </p>

<p>People wouldn't simply lie during a code review to get me to approve a thing and then just ... never follow up... </p>

<h1 id="soshowmeone">so, show me one</h1>

<p>Fundimentally, we have to assume we're working with good faith actors, right?</p>

<p>So it seems fair to just approve the PR, once they show a pair of commits where:</p>

<ul>
<li>The first one sucks, but they said "i got u next time dawg" and </li>
<li>The second one actually fixed the suck from the first commit.</li>
</ul>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="Programming" />

    </entry>
    <entry>
        <title>Oneliners? In my crontab?</title>
<link href="https://alastair.pl/2021/12/08/Oneliners-In-my-crontab-" />
        <link href="https://alastair.pl/2021/12/08/Oneliners-In-my-crontab-.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2021/12/08/Oneliners-In-my-crontab-.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2021/12/08/Oneliners-In-my-crontab-</id>
        <updated>2021-12-08T18:33:06Z</updated>
        <summary>perl -MScript::CleanupExpiredEntries -E&#39;Script::CleanupExpiredEntries-&gt;new_from_args-&gt;run&#39;</summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
<p>You can neatly put all your logic into a signle class, and then have a nice little factory that looks at <code class="language-perl">@ARGV</code>. </p>

<p>If your class has prod configs as defaults, then your crontab looks like this:</p>

<pre><code class="language-perl">* * * * * perl -MMyApp::Script::CleanupExpiredEntries \
                -E'MyApp::Script::CleanupExpiredEntries-&gt;new_from_args-&gt;run'
</code></pre>

<p>Because you don't have any code in a <code class="language-perl">bin/run-me</code> script, you can neatly write tests for all your functions
by either sub-classing your <code class="language-perl">::Script</code> to replace your database access logic or by 
by straight-up replacing the method for the duration of your sub-test with </p>

<pre><code class="language-perl">{
    local *MyApp::Script::CleanupExpiredEntries::fetch_from_db = sub  { ...}
    ...
}
</code></pre>

<p>The most notable downside is that some day someone might introduce some code that uses <code class="language-perl">Log::Log4perl</code>, and a 
config config that references <code class="language-perl">$0</code>:</p>

<pre><code class="language-perl">log4perl.appender.LOGFILE.filename=sub {
    my $name = ( map s{ [.]pl $ }{}xr, split m{/}, $0 )[-1];
    "/var/log/$name/$name.log" }
</code></pre>

<p>which means you'll get a mail a minute saying:</p>

<pre><code class="language-perl"> Can't sysopen /var/log/-e/-e.log (No such file or directory)
    at /usr/share/perl5/Log/Log4perl/Appender/File.pm line 140.
</code></pre>

<p>which might not be the kind of thing you want to see after taking a couple of days off.</p>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="Programming" />

    </entry>
    <entry>
        <title>I like perls scoping</title>
<link href="https://alastair.pl/2021/10/05/I-like-perls-scoping" />
        <link href="https://alastair.pl/2021/10/05/I-like-perls-scoping.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2021/10/05/I-like-perls-scoping.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2021/10/05/I-like-perls-scoping</id>
        <updated>2021-10-05T17:02:17Z</updated>
        <summary>I think it&#39;s chill that perl has both lexical and dynamic scoping.</summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
<p><code class="language-perl">TL;DR</code>: I think it's chill that perl has both lexical and dynamic scoping.</p>

<pre><code class="language-perl">for my $thing (@things) {
    local $ThingFinder::LogLevel = 9;

    print "I have $thing";
    if (my $thing = $thing-&gt;get_more_specific_things()) { 
        print "I have found this thing: $thing";
    }
}
</code></pre>

<h1 id="lexicalvariables">Lexical variables!</h1>

<p>Variables who are only declared / visible within their scope.</p>

<pre><code class="language-perl">my $item = Thing-&gt;new();               # &lt;- declare a lexical variable
                                       #    and shove an object in there
                                       #
for my $thing ($item-&gt;fetch_things) {  # &lt;- $thing only exists within the loop
                                       #
    my $item = $thing&gt;get_item();      # &lt;- this $item masks the $item above
    $item-&gt;do_stuff();                 # &lt;- do_stuff can't see either $item
                                       #    (though the inner one will be "self" in the call)
                                       #
}                                      # &lt;- inner $item is DESTROYed here.
</code></pre>

<p>Lexicals are the power house of the closure:</p>

<pre><code class="language-perl">sub thing_maker {
    my $thing = shift;                  # &lt;- $thing will live past the end of the
                                        #    call to thing_maker
    return sub {                        # &lt;- return a code-ref
        "I made this thing: $thing"     # &lt;- This reference here keeps $thing alive.
    }
}

my $code = thing_maker("very good thing here");
print $code-&gt;()                         # "I made this thing: very good thing here"
</code></pre>

<h1 id="globalsorpackagevariables">Globals or Package variables!</h1>

<p>These are the kind of variables you get if you don't <code class="language-perl">use strict 'vars'</code>.</p>

<pre><code class="language-perl">#!perl
$half = $ARGV[1] / 2;            # &lt;- $half isn't declared with my/our/state
                                 #    so it's ours 
print "Half of that is $half\n"  # "Half of that is 5"  (or whatever)
</code></pre>

<p>These are kind of pesky because the stuff you assign to them is only DESTROYed when 
the variable is assigned over or the interpreter shuts down. </p>

<h2 id="youcanseethemfromoutsidethepackage">You can see them from outside the <code class="language-perl">package</code></h2>

<p>You have a variable in a package:</p>

<pre><code class="language-perl">package ThingFinder;
our $LogLevel = 4;
1
</code></pre>

<p>... and you can see the values in it:</p>

<pre><code class="language-perl">use ThingFinder;

sub show_loglevel {
   say "It's $ThingFinder::LogLevel"; # It's 4
}
</code></pre>

<p>... sadly anyone can write to it too:</p>

<pre><code class="language-perl"># Set the value for everyone forever:
$ThingFinder::LogLevel = 'just any old garbage'; 
</code></pre>

<p>These variables are super helpful for configuration when your package exports functions.</p>

<h2 id="youcanoverridethevalueforthosecalledinsideablockwithlocal">You can override the value for those called inside a block with <code class="language-perl">local</code></h2>

<pre><code class="language-perl">$ThingFinder::LogLevel = 4;             # &lt;- Set the value for everyone forever
ThingFinder-&gt;show_loglevel()            # "It's 4"

{
    local $ThingFinder::LogLevel = 9;   # &lt;- Set the value until the end of the scope
    ThingFinder-&gt;show_loglevel()        # "It's 9"
}
</code></pre>

<p><code class="language-perl">local</code> works on other stuff, like the symbol table, or just regular old hashes, which is also chill. </p>

<h1 id="thatsit.">That's it.</h1>

<p>I just think that's neat.</p>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="Why I like perl" />

    </entry>
    <entry>
        <title>[(a,4),(b,3),(c,2),(a,1)]</title>
<link href="https://alastair.pl/2021/02/05/-a-4-b-3-c-2-a-1-" />
        <link href="https://alastair.pl/2021/02/05/-a-4-b-3-c-2-a-1-.html"
                rel="alternate" type="text/html"
        />
        <link href="https://alastair.pl/2021/02/05/-a-4-b-3-c-2-a-1-.html?is_admin=1"
                rel="edit" 
        />
        <id>https://alastair.pl/2021/02/05/-a-4-b-3-c-2-a-1-</id>
        <updated>2021-02-05T17:20:18Z</updated>
        <summary></summary>

        <content type="xhtml">
            <div xmlns="http://www.w3.org/1999/xhtml">
Re: <a href="https://twitter.com/allenholub/status/1357115515672555520?s=19" rel="noopener" target="_blank" >"an interview question"</a>:<br />

<blockquote>
  <p>Write a function that takes 
   'aaaabbbcca'
  and returns 
    [('a', 4), ('b', 3), ('c', 2), ('a', 1)]</p>
</blockquote>

<p>I'm not sure why an interviewer would hate someone enough to ask a question like this, but this seems like a fair response: </p>

<pre><code class="language-perl">% echo aaaabbbcca | perl -nlE '
    s/((.)\2*)/push @things,sprintf "(%s,%s)", $2,length $1 /ge;
    $"=","; say "[@things]"
'
[(a,4),(b,3),(c,2),(a,1)]
</code></pre>

<p>I mean, it'd be easier if perl had tuples, but that's what you get for answering a python question in perl <em>when nobody asked you to</em> </p>

<h2 id="standardperl-golfhttp:wiki.c2.comperlgolfdisclaimer">Standard <a href="http://wiki.c2.com/?PerlGolf">perl-golf</a> disclaimer</h2>

<p><em>Please don't do this kind of thing in a production code base</em></p>
            </div>
        </content>
        <author>
            <name>Alastair</name>
<email>ignored@localhost</email>
</author>

        <category term="oneliner" />
        <category term="nonsense" />

    </entry>

</feed>
