<?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: Johan Lindstrom</title>
    <description>The latest articles on DEV Community by Johan Lindstrom (@jplindstrom).</description>
    <link>https://dev.to/jplindstrom</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%2F48036%2Fccba1629-b12f-42d6-a4aa-b04c2d0a2b22.jpg</url>
      <title>DEV Community: Johan Lindstrom</title>
      <link>https://dev.to/jplindstrom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jplindstrom"/>
    <language>en</language>
    <item>
      <title>Cheap count(*) in Postgres</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Mon, 11 Nov 2019 17:47:44 +0000</pubDate>
      <link>https://dev.to/jplindstrom/cheap-count-in-postgres-58nj</link>
      <guid>https://dev.to/jplindstrom/cheap-count-in-postgres-58nj</guid>
      <description>&lt;p&gt;Running &lt;code&gt;select count(*) from mytable&lt;/code&gt; in Postgres can be expensive for large tables. Beacause of its MVCC concurrency model it must do a lot of work to get an exact figure.&lt;/p&gt;

&lt;p&gt;If we're not careful the database can start using a lot of CPU, disk IO and cache memory. Not great in production where the database presumably is pretty busy doing other important work...&lt;/p&gt;

&lt;p&gt;But if we're new to a database and just looking around, &lt;strong&gt;we don't care about the exact number&lt;/strong&gt;. We just need to know if it would be dangerous to run queries on the table to start investigating the broken data after that nasty bug.&lt;/p&gt;

&lt;p&gt;There are other ways to do this, but here's a simple and easy-to-remember trick: use the query plan from &lt;code&gt;explain&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;explain&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;my_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                   &lt;span class="n"&gt;QUERY&lt;/span&gt; &lt;span class="n"&gt;PLAN&lt;/span&gt;                                    
&lt;span class="c1"&gt;---------------------------------------------------------------------------------&lt;/span&gt;
 &lt;span class="k"&gt;Aggregate&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1901498&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1901498&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;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="n"&gt;Seq&lt;/span&gt; &lt;span class="n"&gt;Scan&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;my_table&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1815135&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;34545152&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;See that &lt;code&gt;rows=34545152&lt;/code&gt;? That's the rough number of rows in the table.&lt;/p&gt;

&lt;p&gt;35 million. Careful with those full table scans...&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>pg</category>
      <category>database</category>
    </item>
    <item>
      <title>DBIC testing: rs_with_new_rows</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Tue, 18 Jun 2019 12:33:37 +0000</pubDate>
      <link>https://dev.to/jplindstrom/dbic-testing-rswithnewrows-5b11</link>
      <guid>https://dev.to/jplindstrom/dbic-testing-rswithnewrows-5b11</guid>
      <description>&lt;p&gt;Here's a handy little &lt;a href="https://metacpan.org/pod/DBIx::Class"&gt;DBIx::Class&lt;/a&gt; &lt;em&gt;ResultSet&lt;/em&gt; method for when you need to write a test verifying database changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="cm"&gt;=head2 rs_with_new_rows() : $resultset_with_new_data

Resultset with only PK ids which are greater than the currently
largest one, i.e. it will only return rows created going forwards.

Great for testing.

=cut&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;rs_with_new_rows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$max_id&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;get_column&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;max&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;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;$max_id&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;Put that in the base class for your &lt;em&gt;ResultSet&lt;/em&gt; classes to make it available to all of them in one go.&lt;/p&gt;

&lt;p&gt;As you can see, the basic operation is to look for the highest &lt;code&gt;id&lt;/code&gt; column value and then find rows with an id larger than that.&lt;/p&gt;

&lt;p&gt;This brings along a few caveats. First off, the PK column needs to be an ever increasing value (probably an &lt;code&gt;auto_increment&lt;/code&gt; or &lt;code&gt;sequence&lt;/code&gt; depending on your database).&lt;/p&gt;

&lt;p&gt;Second, the PK column obviously needs to be called &lt;code&gt;id&lt;/code&gt;. If that's not the case, you could solve this by using the &lt;a href="https://metacpan.org/pod/DBIx::Class::ResultSource#primary_columns"&gt;primary_columns&lt;/a&gt; method of the &lt;em&gt;ResultSource&lt;/em&gt; class and use that.&lt;/p&gt;

&lt;p&gt;Third, if this were a proper library it should probably be flexible and and robust enough to be used as part of a more complex query, and we should use the &lt;em&gt;ResultSet&lt;/em&gt;  &lt;a href="https://metacpan.org/pod/DBIx::Class::ResultSet#current_source_alias"&gt;current_source_alias&lt;/a&gt; to fully qualify the column names.&lt;/p&gt;

&lt;p&gt;For this simple use case, it works fine though.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finally, let's write that test
&lt;/h1&gt;

&lt;p&gt;Here's how the &lt;code&gt;rs_with_new_rows&lt;/code&gt; method would be used in a test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;note&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*** Setup&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;$tree_node_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;resultset&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;TreeNode&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;rs_with_new_rows&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;note&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*** Run&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="c1"&gt;# Run code under test, which creates tree nodes&lt;/span&gt;

&lt;span class="nv"&gt;note&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*** Test&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tree_node_rs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Correct number of tree nodes created&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;span class="nv"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;$tree_node_rs&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;order_by&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;id&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;first&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;parent_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First (top) tree node has no parent&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 works because of the suuuper nice way we can chain resultsets in DBIC without actually executing any SQL query.&lt;/p&gt;

&lt;p&gt;The method &lt;code&gt;rs_with_new_rows&lt;/code&gt; ends with a call to &lt;code&gt;-&amp;gt;search&lt;/code&gt;, which returns a &lt;em&gt;new&lt;/em&gt; resultset with the fresh search criteria added. The query doesn't run until we ask for some data, e.g. using &lt;code&gt;-&amp;gt;all&lt;/code&gt;, or &lt;code&gt;-&amp;gt;count&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>dbic</category>
      <category>testing</category>
      <category>orm</category>
    </item>
    <item>
      <title>Perl I never write: snippets</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Wed, 12 Jun 2019 19:03:58 +0000</pubDate>
      <link>https://dev.to/jplindstrom/perl-i-never-write-snippets-3ae0</link>
      <guid>https://dev.to/jplindstrom/perl-i-never-write-snippets-3ae0</guid>
      <description>&lt;p&gt;Emacs has this cool package &lt;code&gt;yasnippet&lt;/code&gt;, which is a simple template expansion system.&lt;/p&gt;

&lt;p&gt;So for instance when I'm declaring a method, I can type a simple trigger word: &lt;code&gt;argsm&lt;/code&gt; (args for a method), hit &lt;code&gt;&amp;lt;Tab&amp;gt;&lt;/code&gt; and the trigger word expands into the corresponding template (| is the cursor (or "point" in Emacs parlance)):&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&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="o"&gt;=&lt;/span&gt; &lt;span class="nv"&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 obviously something that needs to be done &lt;em&gt;all. the. time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this case I also use it when there are no method arguments, because it turns out it's way less hassle to type &lt;code&gt;argsm&amp;lt;Tab&amp;gt;&lt;/code&gt; and delete the current line than to type &lt;code&gt;my $self = shift;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Snippets are a very useful mechanism for reducing the &lt;em&gt;friction&lt;/em&gt; of doing common, slightly fiddly things. Reducing friction is important, because it allows you to keep your mind on what you &lt;em&gt;actually&lt;/em&gt; want to accomplish, rather than the rote typing of syntax (and shifty characters like &lt;code&gt;()$@_&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yasnippet&lt;/code&gt; is a good snippets package for Emacs; I'm sure your editor has a similar feature/plugin available.&lt;/p&gt;

&lt;h1&gt;
  
  
  Yasnippets
&lt;/h1&gt;

&lt;p&gt;Here's the actual snippet file &lt;code&gt;snippets/perl-mode/argsm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : methods args -- my $self = shift; my () = @_;&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="k"&gt;my&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;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As part of the snippet expansion, you can hit &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; to move between specific places (tab stops, like &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, etc.) in the snippet, usually to type custom text there. &lt;code&gt;$0&lt;/code&gt; is the final tab stop where the expansion process ends and you can continue editing.&lt;/p&gt;

&lt;p&gt;The tab stop text can also have a default value which can be a string, or come from calling a function, or be mirrored from what you type elsewhere in the snippet.&lt;/p&gt;

&lt;p&gt;This is all quite powerful, especially if you add in some simple elisp functions of your own. We'll see some of these things in action below.&lt;/p&gt;

&lt;p&gt;There's a &lt;em&gt;lot&lt;/em&gt; more to &lt;code&gt;yasnippet&lt;/code&gt;, like different trigger mechanisms,  dropdown menus, completion support, etc. Start small and simple, and take it from there. &lt;/p&gt;

&lt;p&gt;You can find more &lt;code&gt;yasnippet&lt;/code&gt; info and installation instructions at the end of this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Perl snippets
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;yasnippet&lt;/code&gt; comes with a lot of existing little snippets for various languages and modes.&lt;/p&gt;

&lt;p&gt;I don't use most of the canned Perl snippets however: they are mostly regular Perl keyword constructs that aren't a chore to type in the first place. Instead, here are some of the ones I've defined myself, in order of actual usage and utility:&lt;/p&gt;

&lt;h2&gt;
  
  
  Argument unpacking
&lt;/h2&gt;

&lt;p&gt;I use these right after having typed the method skeleton (with &lt;code&gt;autopair-mode&lt;/code&gt; for the braces):&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;basket_total_price&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;h3&gt;
  
  
  argsm
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : methods args -- my $self = shift; my () = @_;&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="k"&gt;my&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;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  args
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : args my () = @_;&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But, wouldn't it be more convenient to include the whole sub skeleton in the snippet, curly braces and all?&lt;/p&gt;

&lt;p&gt;Sure, you could do that. But I find that it pays off to try to hook the automated parts into the flow only where the friction starts to increase, and leave the low friction bits alone. So you type along, and just when it gets annoying, you switch over to inserting a snippet instead.&lt;/p&gt;

&lt;p&gt;In addition, the shorter snippet can be added when editing an already existing sub. This makes the smaller, more targeted piece of text useful in more situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method/sub POD
&lt;/h2&gt;

&lt;p&gt;Writing POD for &lt;em&gt;method signatures&lt;/em&gt; (i.e. the sub name, arguments and return value) is a very good habit: spending more time thinking about what's going on is usually a good thing.&lt;/p&gt;

&lt;p&gt;In some respects doing this is like a half-way house to TDD (ok, maybe fifth-way house), because writing things down makes you think through what the method does, what parameters it takes and what it returns, any special cases that may apply and how things can go wrong. Basically imagining how it should and could be called, while not going all the way to actually writing code to do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  podx
&lt;/h3&gt;

&lt;p&gt;Invoke this just above a sub declaration to expand into boilerplate POD text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : pod above sub -- =head2 name() :&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head2 ${1:`(my-yas-perl-next-sub-name)`}($2) :$3

$0

=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This snippet is a good demonstration of the different tabstops &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, &lt;code&gt;$3&lt;/code&gt; and finally &lt;code&gt;$0&lt;/code&gt;. The first stop is the pre-filled-in subroutine name, and when I hit &lt;code&gt;&amp;lt;tab&amp;gt;&lt;/code&gt; the point jumps to the next place where I can continue to enter the parameters, etc.&lt;/p&gt;

&lt;p&gt;The default value for the sub name is where things gets interesting. The sub name comes from calling the elisp function &lt;code&gt;my-yas-perl-next-sub-name&lt;/code&gt;, which in this case is a simple regex match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight common_lisp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;my-yas-perl-next-sub-name&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;interactive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;save-excursion&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;search-forward-regexp&lt;/span&gt; &lt;span class="s"&gt;"sub +\\([a-z0-9_]+\\)"&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;match-string&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So having this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;podx&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;get_workflow_type_row&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;turns into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="cm"&gt;=head2 |get_workflow_type_row() :



=cut&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;get_workflow_type_row&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and finally this, after documenting the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="cm"&gt;=head2 get_workflow_type_row($workflow_type) : $workflow_type_row | undef

Return a $workflow_type_row for the $workflow_type
(e.g. "multi_role"), or undef if it doesn't exist (either because
it's invalid or because the company has no Workflows with that
$workflow_type).

=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Moo/Moose lazy attribute
&lt;/h2&gt;

&lt;p&gt;These are basic Moo/Moose attributes with a lazy builder, easily the most common style of attribute in our code. And when it's not, the inserted snippet text is easy to adjust.&lt;/p&gt;

&lt;p&gt;Using the trigger words &lt;code&gt;haslm&lt;/code&gt; (Moo) and &lt;code&gt;hasls&lt;/code&gt; (Moose) for this also has the benefit of getting the syntax right, since that is annoyingly different and I can never remember which is which.&lt;/p&gt;

&lt;h3&gt;
  
  
  haslm
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : has =&amp;gt; () Moo attribute with lazy builder&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazy&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;_build_&lt;/span&gt;&lt;span class="p"&gt;$1 {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  hasls
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : has =&amp;gt; () Moose attribute with lazy builder&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="s"&gt;lazy_build&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;_build_&lt;/span&gt;&lt;span class="p"&gt;$1 {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&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;If you look at the part where it says &lt;code&gt;${1:name}&lt;/code&gt; you'll see another cool &lt;code&gt;yasnippet&lt;/code&gt; feature: &lt;em&gt;mirroring&lt;/em&gt;. While we type the attribute name, the builder sub name is updated in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;csv_writer&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazy&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;_build_csv_writer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Other Moo/Moose attributes
&lt;/h2&gt;

&lt;p&gt;For completeness, here are some other less commonly used attribute declarations.&lt;/p&gt;

&lt;h3&gt;
  
  
  hasr
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : has =&amp;gt; () Moose/Moo attribute with required =&amp;gt; 1&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  has
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : has =&amp;gt; () Simple Moose/Moo attribute&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ro&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;h3&gt;
  
  
  hasbm
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : has =&amp;gt; () Moo attribute with lazy "builder" subref&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="s"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  POD fragments
&lt;/h2&gt;

&lt;p&gt;Not as commonly used, but still somewhat useful: POD &lt;code&gt;=head1&lt;/code&gt; sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  podn
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : name with current package -- =head1 NAME&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head1 NAME

${1:`(ps/current-package-name)`} -- $0

=head1 DESCRIPTION

=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This one is interesting in that it reuses the elisp function from &lt;a href="https://metacpan.org/pod/Devel::PerlySense#Edit-Copy-Package-Name"&gt;Devel::PerlySense -- Copy Package Name&lt;/a&gt; to get the string with the current package name, which is what we want for the &lt;code&gt;=head1 NAME&lt;/code&gt; POD section.&lt;/p&gt;

&lt;p&gt;Let's stop typing things that are already known!&lt;/p&gt;

&lt;h3&gt;
  
  
  poda
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : pod =head1 ATTRIBUTES&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head1 ATTRIBUTES
$0
=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  podm
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : pod =head1 METHODS&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head1 METHODS
$0
=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  podcm
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : pod =head1 CLASS METHODS&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head1 CLASS METHODS
$0
=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  pods
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#name : pod =head1 SUBROUTINES&lt;/span&gt;
&lt;span class="c1"&gt;# --&lt;/span&gt;
&lt;span class="cm"&gt;=head1 SUBROUTINES
$0
=cut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Start using &lt;code&gt;yasnippet&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Read more about &lt;code&gt;yasnippet&lt;/code&gt; here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cupfullofcode.com/blog/2013/02/26/snippet-expansion-with-yasnippet/index.html"&gt;Nice introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://joaotavora.github.io/yasnippet/"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/joaotavora/yasnippet"&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.emacswiki.org/emacs/Yasnippet"&gt;EmacsWiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install it from &lt;a href="https://elpa.gnu.org/packages/yasnippet.html"&gt;ELPA&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  __END__
&lt;/h1&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;After reading this I'm sure you've got some great ideas for snippets of your own, or maybe you already have an existing library of useful snippets?&lt;/p&gt;

&lt;p&gt;Please share in the comments! &lt;small&gt;(or over at &lt;a href="https://www.reddit.com/r/perl/comments/c045pj/perl_i_never_write_snippets/"&gt;reddit.com/r/perl&lt;/a&gt;)&lt;/small&gt;&lt;/p&gt;

</description>
      <category>perl</category>
      <category>emacs</category>
      <category>ide</category>
      <category>snippets</category>
    </item>
    <item>
      <title>use List::AllUtils;</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Mon, 12 Nov 2018 14:00:15 +0000</pubDate>
      <link>https://dev.to/jplindstrom/use-listallutils-944</link>
      <guid>https://dev.to/jplindstrom/use-listallutils-944</guid>
      <description>&lt;p&gt;Did you know about the module &lt;a href="https://metacpan.org/pod/List::AllUtils"&gt;List::AllUtils&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;It puts the goodness of &lt;code&gt;List::Utils&lt;/code&gt; and &lt;code&gt;List::MoreUtils&lt;/code&gt; into one nice package. Or... was it &lt;code&gt;List::Util&lt;/code&gt; and &lt;code&gt;List::MoreUtils&lt;/code&gt;? &lt;code&gt;List::MoreUtil&lt;/code&gt;? Or is it actually &lt;code&gt;List::SomeUtil&lt;/code&gt;? &lt;em&gt;Gaaahrhg!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, that's the problem it solves. Now you can forget about which of those modules were named what, &lt;code&gt;use List::AllUtils;&lt;/code&gt; and just go on with your life. It also adds a few more nice functions from &lt;code&gt;List::UtilsBy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Props to &lt;a href="https://metacpan.org/author/DROLSKY"&gt;Dave Rolsky&lt;/a&gt; (&lt;a href="https://twitter.com/houseabsolute"&gt;@houseabsolute&lt;/a&gt; on the Twitter machine) for being lazy on our behalf!&lt;/p&gt;

&lt;h2&gt;
  
  
  RTFM
&lt;/h2&gt;

&lt;p&gt;It's a good idea to be roughly aware what kinds of operations are available for dealing with lists for next time you need them.&lt;/p&gt;

&lt;p&gt;Read the manual on &lt;a href="https://metacpan.org/pod/List::AllUtils"&gt;meta::cpan&lt;/a&gt;, or locally using &lt;code&gt;perldoc&lt;/code&gt; (after installing the module, probably using the &lt;a href="https://metacpan.org/pod/App::cpanminus"&gt;cpanm&lt;/a&gt; client).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;perldoc List::AllUtils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Highlights
&lt;/h2&gt;

&lt;p&gt;Here are a few standard things on the level of basic language features you should know about.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;sum0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uniq&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a few niceties worth taking a look at.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;any&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pairmap&lt;/code&gt;, &lt;code&gt;pairgrep&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pairwise&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;part&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sort_by&lt;/code&gt;, &lt;code&gt;nsort_by&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there are many more useful functions in there.&lt;/p&gt;

&lt;p&gt;Used correctly these could save you a lot of time and bugs by replacing imperative for loops with more expressive and precise flow control.&lt;/p&gt;

&lt;p&gt;Which function helped you out the most? &lt;em&gt;Add to the discussion&lt;/em&gt; below, or &lt;a href="https://www.reddit.com/r/perl/comments/9we8m4/use_listallutils/"&gt;on /r/perl&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>perl</category>
      <category>cpan</category>
      <category>module</category>
      <category>list</category>
    </item>
    <item>
      <title>Pg fulltext search with DBIx::Class</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Mon, 05 Nov 2018 13:46:53 +0000</pubDate>
      <link>https://dev.to/jplindstrom/pg-fulltext-search-with-dbixclass-102k</link>
      <guid>https://dev.to/jplindstrom/pg-fulltext-search-with-dbixclass-102k</guid>
      <description>&lt;p&gt;Recently I wrote an &lt;em&gt;admin interface&lt;/em&gt; for an internal service. It's basically a list of things processed by the service. &lt;/p&gt;

&lt;p&gt;For troubleshooting problems it seemed quite useful to be able to filter the list by some text columns containing parameters and the processed result. Using &lt;em&gt;Postgres fulltext search&lt;/em&gt; turned out to be a trivial affair, so I thought I'd share it here. &lt;/p&gt;

&lt;h2&gt;
  
  
  Fulltext search in Postgres
&lt;/h2&gt;

&lt;p&gt;In Postgres, performing a fulltext search is done using the Text Search datatypes and operators. Here's a &lt;a href="https://www.compose.com/articles/mastering-postgresql-tools-full-text-search-and-phrase-search/" rel="noopener noreferrer"&gt;good introduction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As an example, assume we have a &lt;code&gt;book&lt;/code&gt; table with a &lt;code&gt;blurb&lt;/code&gt; TEXT column containing a free form description of the book.&lt;/p&gt;

&lt;p&gt;Let's find books in &lt;em&gt;The Laundry File&lt;/em&gt; series by &lt;em&gt;Charles Stross&lt;/em&gt;, because the latest one, "The Labyrinth Index" was just published. Yay!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blurb&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blurb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;@@&lt;/span&gt;
    &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'(scifi | sci-fi) &amp;amp; paranormal &amp;amp; bureacracy
    );
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Briefly what's going on here is that the &lt;code&gt;blurb&lt;/code&gt; column is parsed into a &lt;code&gt;tsvector&lt;/code&gt; which contains English words we can match against. The matching is done using the &lt;code&gt;to_tsquery&lt;/code&gt; function, which contains a search query in a certain format. From the example you can probably figure out the overall syntax.&lt;/p&gt;

&lt;p&gt;That's it! Working full text search on any column. Well done Pg!&lt;/p&gt;

&lt;p&gt;There's a lot more to this and I only know the very first things about it, so go read the &lt;a href="https://www.postgresql.org/docs/9.1/static/datatype-textsearch.html" rel="noopener noreferrer"&gt;Postgres manual&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving performance
&lt;/h2&gt;

&lt;p&gt;With the query above, the &lt;code&gt;to_tsvector('english', blurb)&lt;/code&gt; part will run this function for every row, so that's going to be a bit slow.&lt;/p&gt;

&lt;p&gt;In this particular case, the data volumes weren't that huge initially. Even with several thousand rows this felt quite snappy, with queries returning in tens of ms.&lt;/p&gt;

&lt;p&gt;That won't last with increasing data volumes though, so let's create an expression index on the &lt;code&gt;blurb&lt;/code&gt; column for this one query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt; &lt;span class="n"&gt;book_blurb_gin&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blurb&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;Note how &lt;code&gt;to_tsvector('english', blurb)&lt;/code&gt; matches exactly what we did in the query above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search usability
&lt;/h2&gt;

&lt;p&gt;As a good starting point, especially for non-technical users, it's probably a good idea to not overcomplicate things with the &lt;code&gt;tsquery&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;Just say that all words the they type must match the text: construct the &lt;code&gt;tsquery&lt;/code&gt; string yourself by joining words in the user input with &lt;code&gt;' &amp;amp; '&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you do allow your users to enter free-form &lt;code&gt;tsquery&lt;/code&gt; search strings, you'll have to explain it somewhat plainly to them. For &lt;em&gt;technically inclined users&lt;/em&gt;, the briefest explanation I've come up with is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt; between words, and &lt;code&gt;()&lt;/code&gt; to group expressions.&lt;br&gt;
Match 'single-quoted phrases'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Examples are very powerful for conveying details like this. You should pick some useful search terms &lt;em&gt;related to your domain&lt;/em&gt;, maybe similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(scifi | sci-fi) &amp;amp; horror &amp;amp; 'paranormal bureacracy'&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;But do try to include all the available features in the example, because people don't read text, and the example may be the only thing they actually cast their busy eyes at. ¯\&lt;em&gt;(ツ)&lt;/em&gt;/¯&lt;/p&gt;

&lt;h3&gt;
  
  
  Simpler-to-use query formats
&lt;/h3&gt;

&lt;p&gt;In Postgres 11 and onwards, there are more user friendly ways to get user input. Read further about &lt;a href="https://www.postgresql.org/docs/11/static/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES" rel="noopener noreferrer"&gt;plainto_tsquery and websearch_to_tsquery&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  tsquery errors
&lt;/h2&gt;

&lt;p&gt;If the user enters invalid &lt;code&gt;tsquery&lt;/code&gt; syntax, Postgres will throw an exception when the query is executed. You'll need to be prepared to handle that and rephrase the error into something nicer. You can match the error message against this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;syntax error in tsquery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chained DBIx::Class search methods
&lt;/h2&gt;

&lt;p&gt;The Perl module &lt;a href="https://metacpan.org/pod/DBIx::Class" rel="noopener noreferrer"&gt;DBIx::Class&lt;/a&gt; is an ORM on top of the SQL-level DBI module. It is excellent in many ways.&lt;/p&gt;

&lt;p&gt;One of the nicer features of DBIC is &lt;a href="https://metacpan.org/pod/distribution/DBIx-Class/lib/DBIx/Class/Manual/Features.pod#ResultSet-Chaining" rel="noopener noreferrer"&gt;chained resultsets&lt;/a&gt;. This means you can have a resultset object with a &lt;em&gt;where clause&lt;/em&gt; applied to it, and then pass around the object and modify the query by applying further conditions, joining more tables etc.&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;$book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;resultset&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Book&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;$title_book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$book_rs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;title&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;...&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;$title_and_author_book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$title_book_rs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;author&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;...&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;# The query is only executed when we ask for the rows&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@book_rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$title_and_author_book_rs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we can define one of these calls to &lt;code&gt;search&lt;/code&gt; in its own method on the &lt;code&gt;ResultSet::Book&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;search_title_rs&lt;/span&gt;&lt;span class="p"&gt;($self, $title) {&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this is a trivial example, but encapsulating the details about the query into a search method like this makes the actual application code very readable, even when we need to construct quite complicated queries.&lt;/p&gt;

&lt;p&gt;Extracting small query fragments like this is also a good way to ensure that details related to each resultset is placed in the class actually responsible for it, rather than spread around the code base as part of larger queries.&lt;/p&gt;

&lt;p&gt;This technique is what we'll use to search the fulltext column.&lt;/p&gt;

&lt;h2&gt;
  
  
  search_tsquery_rs
&lt;/h2&gt;

&lt;p&gt;Using the &lt;code&gt;to_tsvector&lt;/code&gt; and &lt;code&gt;to_tsquery&lt;/code&gt; syntax in SQL is a bit ardous, and in DBIC it is even more fiddly. But as we just saw it can be nicely encapsulated in a &lt;code&gt;search_tsquery_rs&lt;/code&gt; method that can be chained onto the resultset.&lt;/p&gt;

&lt;p&gt;Put this in the &lt;code&gt;ResultSet::Book&lt;/code&gt; class for your table, or better, in a common base class which all your &lt;code&gt;ResultSet&lt;/code&gt; classes inherit from:&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="cm"&gt;=head2 search_tsquery_rs($column, $tsquery) : $rs

Search the $column as a Postgres tsquery fulltext search.

Use &amp;amp;, |, ! between words, and () to group expressions.

Invalid tsqueries will throw an exception that matches
m/syntax error in tsquery/.

=cut&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;search_tsquery_rs&lt;/span&gt;&lt;span class="p"&gt;($self, $column, $tsquery) {&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;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;to_tsvector('english', &lt;/span&gt;&lt;span class="si"&gt;$column&lt;/span&gt;&lt;span class="s2"&gt;) @@ to_tsquery('english', ?)&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
                &lt;span class="nv"&gt;$tsquery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the peculiarities needed to make this work in DBIC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literal SQL is inserted in the query, but (and this is cool) we can still use placeholders for this&lt;/li&gt;
&lt;li&gt;This feels more like a hack, but to get a syntactically correct &lt;em&gt;where clause&lt;/em&gt;, we need to combine this with an AND operator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can use this method seamlessly in our application code:&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;$book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;resultset&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Book&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;$book_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$book_rs&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s"&gt;author&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;...&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;search_tsquery_rs&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;blurb&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;horror &amp;amp; scifi&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;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling tsquery errors in DBIC
&lt;/h2&gt;

&lt;p&gt;While you can pass around resultset objects and chain them together, the actual SQL query isn't executed until you ask for some data to be returned, e.g. by calling &lt;code&gt;-&amp;gt;all&lt;/code&gt; or &lt;code&gt;-&amp;gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that we can't encapsulate the error message handling inside the &lt;code&gt;search_tsquery_rs&lt;/code&gt; method itself, because it's not necessarily near the place and time where the exception will be thrown.&lt;/p&gt;

&lt;p&gt;Instead you'll have to wrap &lt;em&gt;the place of execution&lt;/em&gt; in an &lt;code&gt;eval&lt;/code&gt; (or better: use &lt;a href="https://metacpan.org/pod/Try::Tiny" rel="noopener noreferrer"&gt;Try::Tiny&lt;/a&gt;) and identify the &lt;code&gt;tsquery&lt;/code&gt; related exception there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;I hope that was a helpful intro to Postgres fulltext search, and how to use it neatly with DBIx::Class.&lt;/p&gt;

&lt;p&gt;To get an idea for how nicely Postgres supports this: all in all, it probably took longer to write up this blog post than to research and implement this for my simple needs. It was also an absolute delight to be using software where well designed parts just seem to work out when composed togeher.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Postgres regex search-method
&lt;/h2&gt;

&lt;p&gt;Sometimes, fulltext search is overkill. So while we're at it, here's how to do a LIKE query, except using Postgres' regular expressions.&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="cm"&gt;=head2 search_regex_rs($column, $regex) : $rs

Search the $column as a Postgres SIMILAR TO regex match.

Invalid regexes will throw an exception that matches
m/invalid regular expression/.

=cut&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;search_regex_rs&lt;/span&gt;&lt;span class="p"&gt;($self, $column, $regex) {&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$self&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nv"&gt;$column&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SIMILAR TO ?&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;$regex&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;



</description>
      <category>postgres</category>
      <category>pg</category>
      <category>perl</category>
      <category>dbic</category>
    </item>
    <item>
      <title>Extract Variable in Emacs</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Thu, 01 Nov 2018 14:02:56 +0000</pubDate>
      <link>https://dev.to/jplindstrom/extract-variable-in-emacs-13f3</link>
      <guid>https://dev.to/jplindstrom/extract-variable-in-emacs-13f3</guid>
      <description>&lt;p&gt;If you're using Emacs to wrangle Perl, here's a useful little refactoring feature you can use:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Extract Variable&lt;/em&gt; - &lt;code&gt;C-o e e v&lt;/code&gt; -- Do the refactoring &lt;em&gt;Extract Variable&lt;/em&gt; of the active region.&lt;/p&gt;

&lt;p&gt;Installation instructions below.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is refactoring again?
&lt;/h2&gt;

&lt;p&gt;Martin Fowler introduced the concept of &lt;em&gt;refactoring&lt;/em&gt; in his 1999 book &lt;a href="https://martinfowler.com/books/refactoring.html"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Refactoring is a way to restructure code to make it easier to work with, while preserving behaviour. Refactoring happens in small predictable steps, with tests passing after each step.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "your system should not be broken
  for more than a few minutes
  at a time"
                   -- Martin Fowler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since then, the original meaning of the term has shifted to mean... really, any old rewrite of existing code, regardless of how large-scale it is, or whether it's actually changing behaviour by fixing a bug or changing requirements.&lt;/p&gt;

&lt;p&gt;These are all legitimate things you can do to a code base, but it's &lt;a href="https://martinfowler.com/bliki/RefactoringMalapropism.html"&gt;not the activity that Fowler set out to describe&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract Variable
&lt;/h2&gt;

&lt;p&gt;Extract Variable is one of the easiest and smallest refactorings to implement while still being quite useful in day-to-day programming. Anything that helps making code clearer on a line or method level is a welcome help.&lt;/p&gt;

&lt;p&gt;It's also easy to work with, because it really only has one step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Walk-through
&lt;/h2&gt;

&lt;p&gt;Here's an example with a piece of code accessing the database config for the application user and the db admin user. The are mostly the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$app&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&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;services&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;db&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;product&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;app&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;$dbadmin&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&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;services&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;db&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;product&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;dbadmin&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Select a piece of code (on either of the lines) that is duplicated a lot within the current subroutine and hit &lt;code&gt;C-o e e v&lt;/code&gt; (mnemonic: Edit - Extract Variable). &lt;/p&gt;

&lt;p&gt;In this case this seems to be the common part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&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;services&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;db&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;product&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will be asked for a variable name to put this in. The default is the last word in the selected code (&lt;code&gt;$product&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;All occurrences of the selection will now be replaced with &lt;code&gt;$product&lt;/code&gt;, and the new variable &lt;code&gt;$product&lt;/code&gt; will be declared just before the earliest usage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$product&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&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;services&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;db&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;product&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;$app&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$product&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;app&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;$dbadmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$product&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;dbadmin&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Before the edit, the &lt;code&gt;mark&lt;/code&gt; was pushed at the location where you started, so you can hit &lt;code&gt;C-u C-SPC&lt;/code&gt; to jump back.&lt;/p&gt;

&lt;p&gt;After the edit, the point is left at the new variable declaration so you can ensure that it is in a reasonable location. It's not unusual to need to move it to an outer scope in order for all the usages to be covered by the declaration.&lt;/p&gt;

&lt;p&gt;Now you need to ensure this edit makes sense. Both replacements and the declaration are highlighted, so it's easy to see what was changed.&lt;/p&gt;

&lt;p&gt;If it's all wrong, just &lt;code&gt;M-x undo&lt;/code&gt; to revert the change.&lt;/p&gt;

&lt;p&gt;Once you've eye-balled the edits, hit &lt;code&gt;C-o e h&lt;/code&gt; to remove the Highlights.&lt;/p&gt;

&lt;p&gt;Note that the replacement is syntax unaware, so you'll have to ensure it's syntactically correct yourself, and placed in a nice spot in the source code (althugh most of the time it works just fine).&lt;/p&gt;

&lt;p&gt;In this particular example, had there been no arrows between the hash keys, the final code would have looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$product&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;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&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;services&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;product&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;$app&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;app&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;$dbadmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;dbadmin&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and that clearly isn't equivalent Perl code, the &lt;code&gt;$product&lt;/code&gt; &lt;em&gt;hashref&lt;/em&gt; being treated as a &lt;em&gt;hash&lt;/em&gt;. This is probably the most common failure mode though, and shouldn't happen that often. Now you know.&lt;/p&gt;

&lt;p&gt;By default, only the current subroutine is changed. Invoke with the prefix arg &lt;code&gt;C-u&lt;/code&gt; to change the entire buffer: &lt;code&gt;C-u C-o e e v&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Neat uses for Extract Variable
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Duplication
&lt;/h4&gt;

&lt;p&gt;Remove duplicated code (duh), beause small-scale duplication is just shoddy, and this opens up an opportunity to introduce well named variables that describes what things &lt;em&gt;are&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Long lines
&lt;/h4&gt;

&lt;p&gt;Break a long unreadable line into two by extracting an (again, well named) temporary variable. This is particularly useful when there's an if-statement with an unreadably long condition.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rename
&lt;/h4&gt;

&lt;p&gt;Rename variable - Extract Variable on a variable name, then just delete the new variable declaration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;resultset&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Book&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;@books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's rename &lt;code&gt;$books&lt;/code&gt; --&amp;gt; &lt;code&gt;$book_rs&lt;/code&gt;. &lt;em&gt;Extract Variable&lt;/em&gt; on &lt;code&gt;$books&lt;/code&gt; turns this into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                      &lt;span class="c1"&gt;# &amp;lt;-- delete this line&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$book_rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$schema&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;resultset&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Book&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;@books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$book_rs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;search&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Point is now on the first declaration, so just delete that line and we're done.&lt;/p&gt;

&lt;h4&gt;
  
  
  Strings
&lt;/h4&gt;

&lt;p&gt;Make method call in string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;So, you want to make a &lt;/span&gt;&lt;span class="si"&gt;$object&lt;/span&gt;&lt;span class="s2"&gt;-&amp;gt;method_call inside a string&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But that doesn't work obviously. There are various ways around that, but one thing you can do is to mark &lt;code&gt;$object-&amp;gt;method_call&lt;/code&gt; to extract it, and end up with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;$method_call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;method_call&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;So, you want to make a &lt;/span&gt;&lt;span class="si"&gt;$method_call&lt;/span&gt;&lt;span class="s2"&gt; inside a string&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Nice!&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Select the repeated code you want to extract. It should be syntactically ready to be assigned to a variable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C-o e e v&lt;/code&gt; to Extract Variable&lt;/li&gt;
&lt;li&gt;Confirm the variable name or enter a better one&lt;/li&gt;
&lt;li&gt;Confirm that the extract makes sense, or fix up the code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C-o e h&lt;/code&gt; to end the refactoring by removing the Highlights&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting the software
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Extract Variable&lt;/em&gt; is available in &lt;a href="https://metacpan.org/pod/Devel::PerlySense"&gt;Devel::PerlySense&lt;/a&gt;, which is a Perl IDE for Emacs. Most of the walkthrough example is actually from the POD of Devel::PerlySense. The key bindings described above is what you get out of the box with PerlySense.&lt;/p&gt;

&lt;p&gt;Install with your regular CPAN client and check out the &lt;a href="https://metacpan.org/pod/Devel::PerlySense#INSTALLATION"&gt;configuration section&lt;/a&gt; for details on how to set it up. This also installs all the elisp code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Extract Variable&lt;/em&gt; is all implemented in Elisp, so if you don't want to install PerlySense, you can instead install the &lt;em&gt;Melpa&lt;/em&gt; package &lt;a href="https://melpa.org/#/lang-refactor-perl"&gt;lang-refactor-perl&lt;/a&gt; which contains this one function. If you do this, you'll have to create your own key bindings though.&lt;/p&gt;

&lt;p&gt;Cool, now go clean up some code! :)&lt;/p&gt;

</description>
      <category>perl</category>
      <category>emacs</category>
      <category>refactoring</category>
    </item>
    <item>
      <title>Carp::Always sometimes</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Tue, 23 Oct 2018 16:53:24 +0000</pubDate>
      <link>https://dev.to/jplindstrom/carpalways-sometimes-obk</link>
      <guid>https://dev.to/jplindstrom/carpalways-sometimes-obk</guid>
      <description>&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;p&gt;Your program just died. Great, now what?&lt;/p&gt;

&lt;p&gt;If the exception string ended with a &lt;code&gt;\n&lt;/code&gt;, it didn't give you a line&lt;br&gt;
number. But even if it did, a line number is often not enough to debug the&lt;br&gt;
problem. That's where the problem occurred, but how did we get there?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacpan.org/pod/Carp::Always"&gt;Carp::Always&lt;/a&gt; to the rescue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Carp::&lt;/span&gt;&lt;span class="nv"&gt;Always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Put this anywhere and all exceptions (and warnings) will have a full&lt;br&gt;
stack trace, including subroutine arguments.&lt;/p&gt;
&lt;h3&gt;
  
  
  But wait...
&lt;/h3&gt;

&lt;p&gt;You probably don't want to turn this on permanently for the entire program. Using &lt;code&gt;Carp::Always&lt;/code&gt; is a global, process-wide change, and the stack trace will be added to &lt;em&gt;all&lt;/em&gt; exceptions, even inside an &lt;code&gt;eval BLOCK&lt;/code&gt;. That's probably not what you wanted.&lt;/p&gt;

&lt;p&gt;So since it's a temporary debugging tool, this is a pretty bad thing&lt;br&gt;
to forget in the code base since it changes &lt;strong&gt;global behaviour&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Do you know that nothing will go weird in the entire rest of your app&lt;br&gt;
now that exceptions will look different? No you do not. So put a&lt;br&gt;
reminder comment you can 'grep' for on the same line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Carp::&lt;/span&gt;&lt;span class="nv"&gt;Always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;### TODO: MyInitials: Remove before committing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yes, it needs to have your initials on it, it's &lt;strong&gt;your personal&lt;br&gt;
responsibility&lt;/strong&gt; to remove this.&lt;/p&gt;
&lt;h3&gt;
  
  
  Preventing mistakes
&lt;/h3&gt;

&lt;p&gt;This low-key way of reminding yourself to not screw up may not be enough. After all, programmers are people, and people forget things and screw up all the time. You may even be one of them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this turns out to be a problem for you&lt;/em&gt; there are several approaches you can take, e.g. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commit hooks in your source control system that prevents them to be checked in&lt;/li&gt;
&lt;li&gt;Automated test that looks through the source tree for any &lt;code&gt;use Carp::Always;&lt;/code&gt; statements&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ad-hoc Carp
&lt;/h3&gt;

&lt;p&gt;Still worried about leaving in the use statements? You can also load the module on the command line with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;perl -MCarp::Always script.pl
prove -MCarp::Always -r t
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;just for that script invocation. Or, to make it semi permanent, set the PERL5OPT variable with this option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export PERL5OPT=-MCarp::Always
perl script.pl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Remember: &lt;code&gt;Carp::Always&lt;/code&gt;, but not all of the time!&lt;/p&gt;

</description>
      <category>perl</category>
      <category>cpan</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>What's the version of that installed Perl module?</title>
      <dc:creator>Johan Lindstrom</dc:creator>
      <pubDate>Thu, 18 Oct 2018 15:23:14 +0000</pubDate>
      <link>https://dev.to/jplindstrom/whats-the-version-of-that-installed-perl-module-m04</link>
      <guid>https://dev.to/jplindstrom/whats-the-version-of-that-installed-perl-module-m04</guid>
      <description>&lt;p&gt;Here's a neat trick to find out what version of a Perl module is installed.&lt;/p&gt;

&lt;p&gt;Let's try with &lt;code&gt;Carp&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;perl -MCarp\ 99999 -e 1

Carp version 99999 required--this is only version 1.42.
BEGIN failed--compilation aborted.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The way this works is that we ask the runtime to load a very high version, and then wait for &lt;code&gt;perl&lt;/code&gt; to apologize that it only has current version x, in this case &lt;code&gt;1.42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note the escaped space between the module and the version:&lt;br&gt;
&lt;code&gt;-MCarp\ 99999&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>cpan</category>
    </item>
  </channel>
</rss>
