<?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>Forem: Matthew O. Persico</title>
    <description>The latest articles on Forem by Matthew O. Persico (@matthewpersico).</description>
    <link>https://forem.com/matthewpersico</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%2F53469%2F985fc523-5328-4d91-be40-b9e93f1dcf7e.jpeg</url>
      <title>Forem: Matthew O. Persico</title>
      <link>https://forem.com/matthewpersico</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/matthewpersico"/>
    <language>en</language>
    <item>
      <title>Being Brave</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Sat, 16 May 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/being-brave-352j</link>
      <guid>https://forem.com/matthewpersico/being-brave-352j</guid>
      <description>&lt;p&gt;I spent a good portion of my day changing browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Like many people, I used Chrome for a long time. When it first came out, it fast, it was responsive, and it wasn’t Internet Explorer. As time passed, it felt as though Chrome was getting less and less responsive and so, when Microsoft released its Chromium rewrite of Edge in January of 2020, I tried it.&lt;/p&gt;

&lt;p&gt;As I remember it, it was much faster and more responsive than Chrome. It also seemed to be a lot easier to sync bookmarks across platforms. I made it my default in Windows and on my iPhone.&lt;/p&gt;

&lt;p&gt;As time passed, Edge also seemed to be getting slower and bloated. The last straw was this past Friday. My laptop actually froze. I had maybe 25 tabs or 30 tabs open. The CPU was pegged at %95. Task manager showed 230 Edge processes.&lt;/p&gt;

&lt;p&gt;There had to be another way. So I googled. And I read. And then I went to use.ai and asked OpenAI GPT-5.5 the question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which browser is the most responsive and uses the least resources?

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

&lt;/div&gt;



&lt;p&gt;I’ll spare you the prose and cut to the chart:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Best choice&lt;/th&gt;
&lt;th&gt;Pick&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lowest resources on Mac&lt;/td&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lowest resources cross-platform&lt;/td&gt;
&lt;td&gt;Brave&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Most responsive benchmark result&lt;/td&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best Windows tab-heavy setup&lt;/td&gt;
&lt;td&gt;Edge with Sleeping Tabs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avoid if RAM is tight&lt;/td&gt;
&lt;td&gt;Chrome, especially with many tabs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I find it funny that Edge is promoted as “Best Windows tab-heavy setup”, given that I experienced the exact opposite result in this situation.&lt;/p&gt;

&lt;p&gt;And so, I decided to move to Brave.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up on Windows
&lt;/h3&gt;

&lt;p&gt;I started on my Windows laptop. I successfully downloaded the install and ran it. Brave then imported all of my bookmarks in from Edge and I set Brave to the default browser. I spent some time hitting my most used sites so that I could enter logins and passwords where needed.&lt;/p&gt;

&lt;p&gt;Chrome uses Google infrastructure (log in with your Google credentials) and Edge uses Microsoft infrastructure (that infamous Microsoft account that you must work really hard to avoid when installing Windows) to share bookmarks across platforms. With Brave, it is different.&lt;/p&gt;

&lt;p&gt;There is an explicit “Sync” section in the Brave Settings. On the first platform where you install Brave, you establish a new ‘sync chain’ and pick which pieces of data to sync with other platforms.&lt;/p&gt;

&lt;p&gt;On subsequent platforms, you go to the same “sync” section, but chose to connect to an existing sync chain. On your original platform you chose to View Sync Code. It can be either a QR code that your phone or camera can scan to sync up&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpjdp7up3ewi3sopchdo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpjdp7up3ewi3sopchdo.jpg" alt="QR code" width="769" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or you can use a string of 25 words to enter on your new computer to allow permissions to sync.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomvydvxl6zssntbc80yr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomvydvxl6zssntbc80yr.jpg" alt="25 words" width="798" height="795"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1 shows my sync device list:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3t6fz9t60zyhn03g7l2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3t6fz9t60zyhn03g7l2.jpg" alt="Figure 1" width="800" height="1014"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of my devices now have a browser with all of the bookmarks I use on all of the devices. It’s very convenient and I like the explicit sync establishment step.&lt;/p&gt;

&lt;p&gt;So far the browser has been solid and responsive. I have not yet tried out the VPN or delved too deeply into functionalities specific to Brave.&lt;/p&gt;

&lt;p&gt;Hopefully, this browser will be responsive for a long time, and I won’t have to try Yet Another Browser any time soon.&lt;/p&gt;

</description>
      <category>browser</category>
      <category>performance</category>
      <category>edge</category>
      <category>bravebrowser</category>
    </item>
    <item>
      <title>My Journey with Devel::ptkdb - Origins</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/my-journey-with-develptkdb-origins-3am0</link>
      <guid>https://forem.com/matthewpersico/my-journey-with-develptkdb-origins-3am0</guid>
      <description>&lt;p&gt;This post explains the beginnings of my involvement with the Perl Tk debugger.&lt;/p&gt;

&lt;h3&gt;
  
  
  Origins
&lt;/h3&gt;

&lt;p&gt;There are a number of well-known schisms in the world of computing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emacs vs Vi&lt;/li&gt;
&lt;li&gt;Tabs vs Spaces&lt;/li&gt;
&lt;li&gt;Perl vs Python&lt;/li&gt;
&lt;li&gt;CLI vs GUI&lt;/li&gt;
&lt;li&gt;Windows vs everything else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d like to add another one: Debuggers vs Print Statements.&lt;/p&gt;

&lt;p&gt;I come down on the side of debuggers. I’m a visual person and I’m impatient. I don’t like to wait for results. I like to get in there, crawl around, change things, see what’s going on.&lt;/p&gt;

&lt;p&gt;I first started using debuggers on &lt;a href="https://en.wikipedia.org/wiki/Digital_Equipment_Corporation" rel="noopener noreferrer"&gt;Digital Equipment Corporation&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/VAX" rel="noopener noreferrer"&gt;VAX&lt;/a&gt; machines running &lt;a href="https://en.wikipedia.org/wiki/OpenVMS" rel="noopener noreferrer"&gt;VMS&lt;/a&gt;. I moved to Unix and used &lt;a href="https://en.wikipedia.org/wiki/GNU_Debugger" rel="noopener noreferrer"&gt;gdb&lt;/a&gt; in &lt;a href="https://www.gnu.org/software/emacs" rel="noopener noreferrer"&gt;Emacs&lt;/a&gt; and then found &lt;a href="https://www.gnu.org/software/ddd/" rel="noopener noreferrer"&gt;ddd&lt;/a&gt;. Any time I started with a new language, one of the first things I reached for was a visual debugger.&lt;/p&gt;

&lt;p&gt;When I started using Perl in the waning years of the last century, I conducted my usual search and found &lt;a href="https://metacpan.org/pod/Devel::ptkdb" rel="noopener noreferrer"&gt;Devel::ptkdb&lt;/a&gt;. It served me well for all the years in which my primary language was Perl. Now, it did have its quirks. The variable display was less than ideal; there was no way to sort the variables in the vertically oriented display list. If you happened to have an array displayed before other variables, then as the array expanded, the other variables would scroll beyond the bottom of the window. The map of loaded modules sometimes did not properly find the related code. The map’s sort order was alphabetical and did not bring the most common modules, nor the local modules, to the top of the list where it would be more convenient to access them.&lt;/p&gt;

&lt;p&gt;Although I might have tried to fix some of these issues, I was intimidated by the fact that this was a debugger, that it was a rather large piece of complicated software that interfaced with the command line Perl debugger. For what it did, it made my programming life much easier, and I was able to work around the quirks.&lt;/p&gt;

&lt;p&gt;That all ended in 2009 when I changed jobs. Perl was no longer my primary environment. I ended up using a proprietary language written by a particular financial institution. There, I was not so intimidated. I enhanced that language’s debugger by adding a screen to manage breakpoints.&lt;/p&gt;

&lt;p&gt;My next job was at a Java shop where I naturally learned how to use the Java debugger in what I think was the Eclipse ecosystem. At this shop, I was given a task to work on an old Perl program. The program read and wrote various files, but the file names were hard coded. They wanted me to make those names variable. In the process of making this change, I had to work on a production system because there was no dedicated development system. In order to make sure that I didn’t disturb production data, I was put on a read-only file system.&lt;/p&gt;

&lt;p&gt;So now I had a chance to go back and work with Perl, and by extension, &lt;code&gt;Devel::ptkdb&lt;/code&gt;. Once I had made my changes, I stepped through the program in the debugger in order to check them. Along the way, I set breakpoints and added variables in the variable display. &lt;code&gt;Devel::ptkdb&lt;/code&gt; allows you to save the breakpoints and the variable list in a &lt;code&gt;.ptkdb&lt;/code&gt; state file, which I did.&lt;/p&gt;

&lt;p&gt;Imagine my surprise when I started up the program again in the debugger and my saved state was not loaded. I scratched my head for about 10 seconds and realized, “Ah, I’m on a read-only partition and the default location of the state file is the directory where the Perl script lives. That location is a read-only file system. Let me save the state file in my home directory.” &lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Imagine my surprise when I started up the program again and my saved state did not reappear again. I scratched my head for a bit more than 10 seconds. I tried it again. It was still not saved. After about half a day of having to reset variables and breakpoints every time I ran the program, I decided that it was high time I took a look at the debugger code. I figured that it had to be something simple, related to just the input box for the name of the state file; it was not even a proper file dialog. I was sure I could handle that.&lt;/p&gt;

&lt;p&gt;I was able to find the issue and correct it. By using the local corrected version of the debugger, I was able to save my state file to any writable directory.&lt;/p&gt;

&lt;p&gt;It was at that point that something clicked in my head. If I could make that fix, maybe I could make other fixes. Maybe I could fix some of the quirks that bothered me all those years ago.&lt;/p&gt;

&lt;p&gt;About two months and a huge changelog later, I had fixed some of those quirks. I fixed the sort problem for the variables. I fixed the mapping problem to the loaded code. I even made some improvements. The debugger used to not reload the state file if you restarted the debugger. Now it did. I programmed in a separate widget that I could use to print messages from inside the debugger while I was debugging the debugger.&lt;/p&gt;

&lt;p&gt;I then realized I probably shouldn’t keep this to myself, so I contacted the author, figuring that they would like to take these changes and update the code. This was approximately 2013, and the debugger hadn’t been touched since 1999. However, it turned out that the author had moved on and would prefer that I just took over the project. I agreed, but before I could talk to legal about trying to let this code out of the shop, I ended up leaving that job.&lt;/p&gt;

&lt;p&gt;I left all these changes behind a corporate firewall.&lt;/p&gt;

&lt;p&gt;And that’s where they stayed. Over the years, I had occasion to use the debugger again, but never quite had the ‘tuits to recreate all these changes.&lt;/p&gt;

&lt;p&gt;Well, now I have the ‘tuits. I’m currently unemployed and I have committed to making a presentation at the next &lt;a href="https://tprc.us/tprc-2026-gsp/" rel="noopener noreferrer"&gt;Perl and Raku Conference&lt;/a&gt; about the debugger. It’s time to roll up my sleeves, dig in and see if I cannot recreate what I did over ten years ago.&lt;/p&gt;

&lt;h5&gt;
  
  
  Footnotes
&lt;/h5&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Which, all these years later begs the question, “If the file system was read only, how did you update the script you were supposed to be changing?” Let’s not let details get in the way of a good story, shall we?  ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>perl</category>
      <category>debug</category>
      <category>gui</category>
      <category>visual</category>
    </item>
    <item>
      <title>Juggling Perl Versions</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/juggling-perl-versions-34m5</link>
      <guid>https://forem.com/matthewpersico/juggling-perl-versions-34m5</guid>
      <description>&lt;p&gt;This article was originally published in The Perl Journal in January of 2003. The first releases of &lt;a href="https://github.com/tokuhirom/plenv" rel="noopener noreferrer"&gt;plenv&lt;/a&gt; and &lt;a href="https://metacpan.org/pod/App::perlbrew" rel="noopener noreferrer"&gt;perlbrew&lt;/a&gt; appear to be in 2013 and 2010 respectively. Please, keep that in mind as you read.&lt;/p&gt;

&lt;p&gt;The original website for The Perl Journal no longer exists. An archive of this article can be found on a personal site that seems to be hosting the old &lt;a href="https://jacobfilipp.com/DrDobbs/articles/TPJ/2003/0301/0301a/0301a.htm" rel="noopener noreferrer"&gt;Dr. Dobbs&lt;/a&gt; site. Since that seems rather tenuous to me, I took that text and have now rehosted the article on my own blog.&lt;/p&gt;

&lt;p&gt;Finally, this was picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Perl Journal January 2003
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Juggling Perl Versions
&lt;/h3&gt;

&lt;h3&gt;
  
  
  By Matthew O. Persico
&lt;/h3&gt;

&lt;p&gt;Managing change when you maintain a sizable Perl installation isn’t easy. Inevitably, one of your colleagues will come to you and say, “I was looking at CPAN and you know, I could save myself two weeks of work if I could install the &lt;code&gt;Foo::Bar&lt;/code&gt; module for use in my Yadayadayada project. Can we get it installed?”&lt;/p&gt;

&lt;p&gt;“Sure,” you reply. “I’ll get right on it.” You download the tarball from CPAN, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gtar zxvf Foo-Bar-1.68.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;Foo-Bar-1.68
perl Makefile.PL

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

&lt;/div&gt;



&lt;p&gt;and then you see it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Perl v5.8.0 required—this is only v5.6.1, stopped at Bar.pm line 2.

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

&lt;/div&gt;



&lt;p&gt;Okay, now what? Well, you can try to find a version of &lt;code&gt;Foo::Bar&lt;/code&gt; that works with 5.6.1, but the odds are there isn’t one. Even if there is such a version, it is probably old enough that it is missing needed functionality or has bugs that are fixed in later versions.&lt;/p&gt;

&lt;p&gt;You could say, “Sorry, we can’t support it,” and you might even get away with that for just one module or just one project.&lt;/p&gt;

&lt;p&gt;Eventually, however, the modules you support are going to be upgraded, new modules will be required, and your version of Perl is not going to support them.&lt;/p&gt;

&lt;p&gt;That’s the point where you start to consider an upgrade of Perl.&lt;/p&gt;

&lt;p&gt;However, by this time, you’ve discovered that there are hundreds of Perl scripts and modules used in production. Every one of them will have to be regression tested before upgrading. Regression testing takes time away from development. Try selling &lt;em&gt;that&lt;/em&gt; to your end users.&lt;/p&gt;

&lt;p&gt;The cost of upgrading any programming language environment is not trivial. You must make sure that every program works in the new environment in the same manner as it did in the old environment before you switch over to the new one. In addition, as more and more operating systems (at least in the *NIX and Linux worlds) come with default installations of Perl that are critical to the smooth operation of the system, upgrading Perl or its default modules can negatively impact the operating system’s performance.&lt;/p&gt;

&lt;p&gt;It seems nearly impossible to safely upgrade Perl without a massive amount of testing. But there is a solution. Instead of upgrading Perl, you can “side-grade” it. This article will describe how to install and maintain multiple versions of Perl on a machine in a transparent and flexible manner. In this manner, you can port scripts on an as-needed basis and maintain multiple versions for testing on your development machines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Principles
&lt;/h3&gt;

&lt;p&gt;In order to maintain multiple versions of Perl in an environment, we set down the following principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do no harm.&lt;/strong&gt; A user or process that knows nothing about our Perl-swapping environment should be presented with the default Perl environment that comes “out-of-the-box.” This means that all paths should have default values that allow a process to use Perl without having to explicitly call any special functions or explicitly set any special environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No pain, all gain.&lt;/strong&gt; The method for changing Perl versions should be as painless as possible. Ideally, one command should do it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can go back.&lt;/strong&gt; There is no reason why the default version of Perl shouldn’t be considered just another version of Perl to be swapped. You should be able to switch back to the default version of Perl as easily as to any other version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To this end, we will create a shell script called &lt;code&gt;perl.sh&lt;/code&gt; to be placed in the &lt;code&gt;/etc/profile.d&lt;/code&gt; directory and called from &lt;code&gt;/etc/profile&lt;/code&gt; upon login. It will create all functions needed to set a particular version of Perl in the environment, and it will set the default environment when first invoked.&lt;/p&gt;

&lt;p&gt;I’ll describe how to build &lt;code&gt;perl.sh&lt;/code&gt; step by step. This is the easiest way to show you how to build the environment yourself, which will probably be necessary; your Perl may be in a different place, your modules may be scattered over multiple directories, and you may have a different version of Perl than I am describing here. Use this article and its code as a template—do not expect to drop this version of &lt;code&gt;perl.sh&lt;/code&gt; onto your system without alteration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standardizing the Default Perl Version
&lt;/h3&gt;

&lt;p&gt;The first step is to get the default version of Perl properly set up using &lt;code&gt;perl.sh&lt;/code&gt;. This will take a bit of work because the default version of Perl is already set up, so we do not want to clobber it when &lt;code&gt;perl.sh&lt;/code&gt; is invoked the first time around. However, we must make sure that we can get back to the default version from another installed version if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Determine Locations
&lt;/h3&gt;

&lt;p&gt;We need to get the locations of the Perl binary, modules, and manpages. One could use &lt;code&gt;perldoc&lt;/code&gt; instead of manpages, but having the Perl manpages available is convenient if you are using GUI &lt;code&gt;man&lt;/code&gt; tools.&lt;/p&gt;

&lt;p&gt;First, execute the command &lt;code&gt;which perl&lt;/code&gt;. In this case, the result is &lt;code&gt;/usr/bin/perl&lt;/code&gt;, which tells us two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Where the Perl binary lives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is on a directory in &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, execute &lt;code&gt;perl -V&lt;/code&gt;. We ignore the build information for the moment and focus on the tail end of the output, which is shown in Example 1.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Characteristics of this binary (from libperl):
  Compile-time options:
  Built under linux
  Compiled at Feb 21 2002 01:00:32
  @INC:
    /usr/lib/perl5/5.6.1/i386-linux
    /usr/lib/perl5/5.6.1
    /usr/lib/perl5/site_perl/5.6.1/i386-linux
    /usr/lib/perl5/site_perl/5.6.1
    /usr/lib/perl5/site_perl
    .

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

&lt;/div&gt;



&lt;p&gt;What this tells us is that there are no other known locations for Perl modules other than the default locations. Practically, that means that &lt;code&gt;PERL5LIB&lt;/code&gt; is not set and that all modules added to the system must be installed into &lt;code&gt;/usr/lib/perl5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My personal philosophy on the subject of installation locations is simple: If I didn’t build it, I won’t write to it. I install all modules added to the system into another directory, even those that are upgrades of modules that are part of the out-of-the-box installation. Upgrading the default version of Perl or its modules in place could cause operating-system components to fail (as previously discussed). Furthermore, if you need to rebuild your system, you will have yet another item to attend to—rebuilding all the modules you added to or updated in the default location. If these modules are installed elsewhere, then when you restore the same version of Perl under which the modules were originally installed to the default location, the add-on modules should be immediately available (assuming you unmounted and did not reformat that partition in the rebuild). Finally, one can, if necessary, cut off access to the upgraded versions by removing the directory from &lt;code&gt;PERL5LIB&lt;/code&gt; and allow usage of the default modules since they still exist in the original Perl tree.&lt;/p&gt;

&lt;p&gt;I am going to establish &lt;code&gt;/opt/perl/lib&lt;/code&gt; as the location for my new modules. I am doing this because I consider Perl to be a product unto itself. &lt;code&gt;/usr&lt;/code&gt; and &lt;code&gt;/usr/local&lt;/code&gt; are good places to stash shared objects like libraries or executables. Perl, however, has a pretty intricate directory structure of its own. Isolating the structure makes it easier to do our environment modifications to swap versions later.&lt;/p&gt;

&lt;p&gt;The exact setting of &lt;code&gt;PERL5LIB&lt;/code&gt; that is needed to produce a valid @INC seems to have changed from release 5.004_04 through 5.005, 5.6.0, 5.6.1, and 5.8.0. Furthermore, the end result is highly dependent on where and how Perl is configured and installed in the first place. Rather than try to determine the settings via the documentation, I suggest you determine it empirically with these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code&gt;/opt/perl&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grab any module from CPAN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unwind the tarball and perform the magic incantations:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;perl Makefile.PL
make &lt;span class="nb"&gt;test install &lt;/span&gt;&lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/perl

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Take note of where the module is installed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You’ll notice that I set &lt;code&gt;PREFIX&lt;/code&gt; at installation time. This is a result of the environment in which I was trained. By setting &lt;code&gt;PREFIX&lt;/code&gt; at install time instead of Makefile at creation time, I can use the same tarball tree to install to a local testing area, a global testing area, and a production area without having to reexecute &lt;code&gt;perl Makefile.PL&lt;/code&gt; each time. You may feel differently. Feel free to specify &lt;code&gt;PREFIX&lt;/code&gt; at &lt;code&gt;perl Makefile.PL&lt;/code&gt; time. The only caveat is that you must be consistent. Pick one method and stick with it. I vaguely recall that in one version of Perl, the end location of the module was different depending on which method was used. This is another example of why I am demonstrating the empirical method of building this framework.&lt;/p&gt;

&lt;p&gt;Finally, test &lt;code&gt;man&lt;/code&gt; capabilities. When I try &lt;code&gt;man perl&lt;/code&gt;, the manpage appears. This indicates that we can get to the manpages in Section 1 for Perl commands. When I try &lt;code&gt;man ExtUtils::MakeMaker&lt;/code&gt;, the manpage does not appear. A quick check of the environment reveals that there is no &lt;code&gt;MANPATH&lt;/code&gt; environment variable set. Therefore, &lt;code&gt;man&lt;/code&gt; is using its own heuristics to determine where manpages are located. By reexamining the top of the &lt;code&gt;perl -V&lt;/code&gt; output, we see the information in Example 2.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 2: Determining default manpath information from the output of perl -V.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
  Platform:
    osname=linux, osvers=2.4.16-6mdksmp, archname=i386-linux
    uname='linux bi.mandrakesoft.com 2.4.16-6mdksmp #1 smp sat dec 8 04:02:48 cet 2001 i686 unknown'
    config_args='-des -Darchname=i386-linux -Dd_dosuid -Ud_csh -Duseshrplib -Doptimize=-O3 -fomit-frame-pointer -pipe -mcpu=pentiumpro -march=i586 -ffast-math -fno-strength-reduce -Dprefix=/usr -D_ndbm -D_gdbm -D_shadow_syslog -Uuselargefiles -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/lib/perl5/man/man3'

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

&lt;/div&gt;



&lt;p&gt;The flag &lt;code&gt;-Dman3dir&lt;/code&gt; defines a location for module manpages that is not going to appear in a default manpath due to its location, which is not “near” a &lt;code&gt;PATH&lt;/code&gt; entry. Even if this path did appear in the default manual path, it would not help us. Without a &lt;code&gt;MANPATH&lt;/code&gt; variable to manipulate, we are not going to be able to swap in manpages that correspond to the version of Perl that we want to change. So, the first order of business is to fix this.&lt;/p&gt;

&lt;p&gt;In most versions of &lt;code&gt;man&lt;/code&gt;, setting &lt;code&gt;MANPATH&lt;/code&gt; completely overrides &lt;code&gt;man&lt;/code&gt;’s heuristics; it does not add new paths to the default ones. This is not a problem, however. There is usually a program &lt;code&gt;manpath&lt;/code&gt; that will print the default paths used by &lt;code&gt;man&lt;/code&gt; in the absence of a &lt;code&gt;MANPATH&lt;/code&gt; variable. So, we create &lt;code&gt;man.sh&lt;/code&gt; and put it in &lt;code&gt;/etc/profile.d&lt;/code&gt;. This ensures that the variable is set for each login process. The contents of &lt;code&gt;man.sh&lt;/code&gt; are simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MANPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'manpath'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;MANPATH

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

&lt;/div&gt;



&lt;p&gt;This is strict Bourne Shell syntax. Korn or bash users can try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MANPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;manpath&lt;span class="si"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;I will use bash shell syntax from now on. Bourne Shell users can make the necessary adjustments.&lt;/p&gt;

&lt;p&gt;Now we will be able to alter the &lt;code&gt;man&lt;/code&gt; environment to match our Perl environment. It might be argued that setting &lt;code&gt;MANPATH&lt;/code&gt; to override &lt;code&gt;man&lt;/code&gt;’s heuristics defeats the purpose of having them. In truth, the only time it matters is when installing new software. Without a &lt;code&gt;MANAPTH&lt;/code&gt; set, &lt;code&gt;man&lt;/code&gt; will automatically find the new &lt;code&gt;man&lt;/code&gt; directory if it is “close” to a directory on the &lt;code&gt;PATH&lt;/code&gt;. But a new &lt;code&gt;PATH&lt;/code&gt; entry is only available to processes that log in after installation, unless a process (or more likely a user) resets &lt;code&gt;PATH&lt;/code&gt;. Logging out and in again should rerun the &lt;code&gt;/etc/profile.d&lt;/code&gt; files, including our new &lt;code&gt;manpath.sh&lt;/code&gt;, which will reexecute the &lt;code&gt;manpath&lt;/code&gt; call and pick up any newly installed manpages if they follow the heuristics.&lt;/p&gt;

&lt;p&gt;Create the &lt;code&gt;set&lt;/code&gt; and &lt;code&gt;unset&lt;/code&gt; Functions&lt;/p&gt;

&lt;p&gt;We will create a function named &lt;code&gt;set_perl_5.6.1&lt;/code&gt;. It will perform three functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;PATH&lt;/code&gt; so that the 5.6.1 version of Perl is on the path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;PERL5LIB&lt;/code&gt; so that any extra libraries are found.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;MANPATH&lt;/code&gt; so that the Perl manpages are located.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;set_perl_5.6.1&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5.6.1
  addpath &lt;span class="nt"&gt;-f&lt;/span&gt; PATH /opt/perl/bin
  add_perl5lib /opt/perl
  addpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /usr/lib/perl5/man
  addpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /opt/perl/lib/perl5/man
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PERL_CURRENT_VERSION&lt;/code&gt; is defined in order to keep track of what version we are currently running. &lt;code&gt;addpath&lt;/code&gt; is a function that will add a directory to a &lt;code&gt;PATH&lt;/code&gt;-like environment variable. It makes use of the &lt;code&gt;PERL_DEFAULT&lt;/code&gt; variable. See Listing 1 for the code. &lt;code&gt;addpath&lt;/code&gt; and &lt;code&gt;delpath&lt;/code&gt; are translations of shell scripts and are described in the following &lt;em&gt;Linux Journal&lt;/em&gt; articles: &lt;a href="http://www.linuxjournal.com/article/3645" rel="noopener noreferrer"&gt;Shell Functions and Path Variables, Part 1&lt;/a&gt;, &lt;a href="http://www.linuxjournal.com/article/3768" rel="noopener noreferrer"&gt;Shell Functions and Path Variables, Part 2&lt;/a&gt;, and &lt;a href="http://www.linuxjournal.com/article.php/3935" rel="noopener noreferrer"&gt;Shell Functions and Path Variables, Part 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this case, we add &lt;code&gt;/opt/perl/bin&lt;/code&gt; to&lt;code&gt;PATH&lt;/code&gt; because there are modules (such as &lt;code&gt;DBI&lt;/code&gt;) that create binaries. This is where they will end up when installed. Why not &lt;code&gt;/opt/perl/bin/5.6.1&lt;/code&gt; or &lt;code&gt;/opt/perl/5.6.1/bin&lt;/code&gt;? Because when we execute &lt;code&gt;make install PREFIX=/opt/perl&lt;/code&gt;, the remainder of the paths are taken from Perl’s current configuration, and the configuration, in this case, is to put all binaries into &lt;code&gt;$PREFIX/bin&lt;/code&gt;. &lt;code&gt;add_perl5lib&lt;/code&gt; is another function, presented in Example 3 with its relatives.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 3: The add_perl5lib function.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;add_perl5lib &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  guts_perl5lib &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; add
&lt;span class="o"&gt;}&lt;/span&gt;

del_perl5lib &lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  guts_perl5lib &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; del
&lt;span class="o"&gt;}&lt;/span&gt;

guts_perl5lib &lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;find &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/lib &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; d | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;path &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; PERL5LIB &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;done
  &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;PERL5LIB
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We find the directories corresponding to the current version of Perl under the requested top-level directory and add or delete them from the &lt;code&gt;PERL5LIB&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;The corresponding &lt;code&gt;unset&lt;/code&gt; function is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unset_perl_5.6.1&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  delpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /opt/perl/lib/perl5/man
  delpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /usr/lib/perl5/man
  del_perl5lib /opt/perl
  delpath &lt;span class="nt"&gt;-f&lt;/span&gt; PATH /opt/perl/bin
  &lt;span class="nb"&gt;unset &lt;/span&gt;PERL_CURRENT_VERSION
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;delpath&lt;/code&gt; is a function that will add a directory to a &lt;code&gt;PATH&lt;/code&gt;-like environment variable; see Listing 2. Detailed discussion of the function is beyond the scope of this article.&lt;/p&gt;

&lt;p&gt;You will notice that the actions in the &lt;code&gt;unset&lt;/code&gt; function are performed in inverse order of the corresponding &lt;code&gt;set&lt;/code&gt; actions. Although this is not strictly required, it is imperative that the setting and unsetting of &lt;code&gt;PERL_CURRENT_VERSION&lt;/code&gt; be the first and last actions of their respective functions. All of the other functions make use of the value of &lt;code&gt;PERL_CURRENT_VERSION&lt;/code&gt;, so it must be available to execute the actions.&lt;/p&gt;

&lt;p&gt;Add all of this code to &lt;code&gt;perl.sh&lt;/code&gt; and all the defaults are now defined for your out-of-the-box version of Perl.&lt;/p&gt;

&lt;p&gt;As a last note, notice that we do not add or delete the default path for Perl from &lt;code&gt;PATH&lt;/code&gt;. There are a number of reasons. In most cases, the path for the default version of Perl is shared. In this case, removing &lt;code&gt;/usr/bin&lt;/code&gt; from&lt;code&gt;PATH&lt;/code&gt; would have dire consequences. A similar argument applies to the default &lt;code&gt;MANPATH&lt;/code&gt; entry &lt;code&gt;/usr/share/man&lt;/code&gt; where the section 1 manpages live.&lt;/p&gt;

&lt;p&gt;You always want to leave a minimum version of Perl in &lt;code&gt;PATH&lt;/code&gt; because the &lt;code&gt;addpath&lt;/code&gt; and &lt;code&gt;delpath&lt;/code&gt; utilities use Perl to do their magic.&lt;/p&gt;

&lt;p&gt;Up to this point, this all has been an interesting exercise, but without a second version of Perl, there is really no reason to have gone through all this work. Let’s install another version of Perl.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a New Version of Perl
&lt;/h3&gt;

&lt;p&gt;I will demonstrate by installing version 5.8.0 into &lt;code&gt;/opt/perl&lt;/code&gt;. During the configure phase (which I invoke using &lt;code&gt;sh Configure&lt;/code&gt;), I take all the default values except for the prompts shown in Example 4.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 4: Configure questions for which you must override the defaults.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Installation prefix to use? (~name ok) [/usr/local] /opt/perl

Pathname where the public executables will reside? (~name ok) [/opt/perl/bin] /opt/perl/bin/5.8.0

Many scripts expect perl to be installed as /usr/bin/perl.
I can install the perl you are about to compile also as /usr/bin/perl
(in addition to /opt/perl/bin/5.8.0/perl).
Do you want to install perl as /usr/bin/perl? [y] n

Where do the main Perl5 manual pages (source) go? (~name ok)
[/opt/perl/man/man1] /opt/perl/man/5.8.0/man1

Pathname where the add-on public executables should be installed? (~name ok) [/opt/perl/bin] /opt/perl/bin/5.8.0

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

&lt;/div&gt;



&lt;p&gt;Subsequent questions will have their defaults altered based on these answers. (For example, we will not need to explicitly set the &lt;code&gt;man&lt;/code&gt; directory for modules [section 3]. Configure is smart enough to change the default to &lt;code&gt;/opt/perl/man/5.8.0/man3&lt;/code&gt; given the setting of man1.) I do not show those questions here since all you have to do is hit RETURN to take the now modified defaults. In order to make installation a bit smoother, create the directory &lt;code&gt;/opt/perl/bin/5.8.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and unset &lt;code&gt;PERL5LIB&lt;/code&gt; (if you’ve set it) before starting Configure. Example 4 above shows the questions for which you must override the defaults.&lt;/p&gt;

&lt;p&gt;Notice that we chose the location for the version number in &lt;code&gt;/opt/perl/bin/5.8.0&lt;/code&gt; and &lt;code&gt;/opt/perl/man/5.8.0/man1&lt;/code&gt; in order to mimic the structure of the lib directory that this version of Perl builds. This is not standard practice. It does, however, make our swapping code much easier to create.&lt;/p&gt;

&lt;p&gt;Once configured, complete the installation with&lt;/p&gt;

&lt;p&gt;make test install&lt;/p&gt;

&lt;h3&gt;
  
  
  Determine Locations
&lt;/h3&gt;

&lt;p&gt;We now need to get the location of the 5.8.0 Perl binary, modules and manpages.&lt;/p&gt;

&lt;p&gt;The location of &lt;code&gt;perl&lt;/code&gt; is easy since we specified it: &lt;code&gt;/opt/perl/ bin/5.8.0&lt;/code&gt;. Make sure that &lt;code&gt;PERL5LIB&lt;/code&gt; is unset and execute &lt;code&gt;/opt/perl/ bin/5.8.0/perl -V&lt;/code&gt;. Again, we are only interested in the tail; see Example 5.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 5: The output of perl -V after installing 5.8.0.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Characteristics of this binary (from libperl):
  Compile-time options: USE_LARGE_FILES
  Built under linux
  Compiled at Dec 3 2002 23:42:03
  @INC:
    /opt/perl/lib/5.8.0/i686-linux
    /opt/perl/lib/5.8.0
    /opt/perl/lib/site_perl/5.8.0/i686-linux
    /opt/perl/lib/site_perl/5.8.0
    /opt/perl/lib/site_perl
    .

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

&lt;/div&gt;



&lt;p&gt;Now, unlike our 5.6.1 installation, we can proceed without setting &lt;code&gt;PERL5LIB&lt;/code&gt; and allow modules to be installed right into &lt;code&gt;/opt/perl/lib/site_perl&lt;/code&gt;. After all, we built this version and, therefore, have no default installation to preserve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the &lt;code&gt;set&lt;/code&gt; and &lt;code&gt;unset&lt;/code&gt; Functions
&lt;/h3&gt;

&lt;p&gt;We will create a function named &lt;code&gt;set_perl_5.8.0&lt;/code&gt;. It will perform three functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set&lt;code&gt;PATH&lt;/code&gt; so that the 5.8.0 version of Perl is on the path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;PERL5LIB&lt;/code&gt; so that any extra libraries are found.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;code&gt;MANPATH&lt;/code&gt; so that the Perl manpages are located.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;set_perl_5.8.0&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5.8.0
  addpath &lt;span class="nt"&gt;-f&lt;/span&gt; PATH /opt/perl/bin/5.8.0
  addpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /opt/perl/man/5.8.0
&lt;span class="o"&gt;}&lt;/span&gt;
The corresponding _unset_ &lt;span class="k"&gt;function &lt;/span&gt;is:
unset_perl_5.8.0&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  delpath &lt;span class="nt"&gt;-f&lt;/span&gt; MANPATH /opt/perl/man/5.8.0
  delpath &lt;span class="nt"&gt;-f&lt;/span&gt; PATH /opt/perl/bin/5.8.0
  &lt;span class="nb"&gt;unset &lt;/span&gt;PERL_CURRENT_VERSION
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Add these two functions to &lt;code&gt;perl.sh&lt;/code&gt; and we’re almost finished.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the &lt;code&gt;swap_perl&lt;/code&gt; Function
&lt;/h3&gt;

&lt;p&gt;The last function to consider is the one that actually does the swapping. You could always code something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unset_perl_&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
swap_perl_5.8.0

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

&lt;/div&gt;



&lt;p&gt;before all calls to Perl, but that gets tedious after a while and is highly error prone. Listing 3 shows the function &lt;code&gt;swap_perl&lt;/code&gt; with commentary. In order to use the function, simply call it before executing any Perl script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swap_perl 5.8.0
perl foobar.pl

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

&lt;/div&gt;



&lt;p&gt;If you keep project-specific library locations, you can add them via arguments to &lt;code&gt;swap_perl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swap_perl 5.8.0 /opt/myCompany/yadayadayada

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

&lt;/div&gt;



&lt;p&gt;The last lines in &lt;code&gt;perl.sh&lt;/code&gt; should set the default Perl environment. Example 6 shows the specifics of our installation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 6: Setting the default Perl environment in perl.sh.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## PERL_DEFAULT is used by various utilities that need to have&lt;/span&gt;
&lt;span class="c"&gt;## access to some version of Perl while we are in the middle of&lt;/span&gt;
&lt;span class="c"&gt;## swapping Perl versions. See addpath and delpath for example.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PERL_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/perl

&lt;span class="c"&gt;## This setting tells swap_perl that there is no current version to&lt;/span&gt;
&lt;span class="c"&gt;## swap out of before swapping in the requested version.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'initial'&lt;/span&gt;

&lt;span class="c"&gt;## Do it&lt;/span&gt;
swap_perl 5.6.1

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Perl Version Selection and the Shebang Line
&lt;/h3&gt;

&lt;p&gt;Perl scripts are usually executed by setting their protection mode to executable (+x in the *NIX and Linux worlds) and invoking the script directly. By placing a shebang line at the top of the script, the shell will invoke the specified program in order to process the script. The usual shebang line is something like:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;The problem with this is that it totally defeats the mechanism of putting the desired Perl executable in the &lt;code&gt;PATH&lt;/code&gt;. One way around this is to modify the shebang line:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;From the manpage header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env - run a program in a modified environment

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

&lt;/div&gt;



&lt;p&gt;In this usage, we do not modify the environment with the assignment of any variables; we simply use env’s &lt;code&gt;PATH&lt;/code&gt;-searching capabilities to find the version of Perl we desire.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shell Game
&lt;/h3&gt;

&lt;p&gt;In order to swap versions of Perl on a case-by-case basis, you have to invoke &lt;code&gt;swap_perl&lt;/code&gt; before any call to Perl. For &lt;code&gt;at&lt;/code&gt; jobs, you must either call &lt;code&gt;swap_perl&lt;/code&gt; in the job definition or in your own environment before the &lt;code&gt;at&lt;/code&gt; job is created. For &lt;code&gt;cron&lt;/code&gt; jobs or commercial job schedulers such as AutoSys, you may have to wrap the command in a shell that calls &lt;code&gt;swap_perl&lt;/code&gt; before invoking the Perl script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Never Look Back
&lt;/h3&gt;

&lt;p&gt;One of the potential disadvantages of having multiple versions of Perl is the need to install new modules in both places. I avoid that problem with the following policy: Once a new version of Perl has been tested enough to go into production, it is placed there with the latest version of all modules that have been installed with the last version. Any new module installations are performed on the new version only. If a developer wants/needs a new module or a module upgrade, he must migrate to the latest Perl version in order to access the module. An exception to this policy can be made for a show-stopping production bug. However, the developer will be highly encouraged to migrate immediately.&lt;/p&gt;

&lt;p&gt;You should suggest that your developers put a &lt;code&gt;swap_perl&lt;/code&gt; statement in their profiles (&lt;code&gt;.bash_profile&lt;/code&gt; in bash) so that they are always working in the latest version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perl Versions Prior to 5.6.0
&lt;/h3&gt;

&lt;p&gt;The directory layout of Perl has evolved over the years. If any of the versions of Perl that you are dealing with are earlier than 5.6.0, you may have to do some more experimentation in setting &lt;code&gt;PERL5LIB&lt;/code&gt; in order to have @INC properly set. This may, in turn, require you to put version-specific code in the &lt;code&gt;add_perl5lib&lt;/code&gt; function. &lt;code&gt;add_perl5lib&lt;/code&gt; can be useful in its own right—I use &lt;code&gt;add_perl5lib&lt;/code&gt; and &lt;code&gt;del_perl5lib&lt;/code&gt; at the command line to temporarily choose between multiple versions of a module that I have installed in separate local trees in order to test the effect of upgrading a modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Here is a summary of the steps needed to maintain multiple versions of Perl:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Determine the default locations of the Perl binary, modules, and manpages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code&gt;set&lt;/code&gt; and &lt;code&gt;unset&lt;/code&gt; functions for this version of Perl. Place them in &lt;code&gt;perl.sh&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install new versions of Perl, taking care to isolate them in highly version-numbered directory structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine the locations of the Perl binary, modules, and manpages for the new version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create &lt;code&gt;set&lt;/code&gt; and &lt;code&gt;unset&lt;/code&gt; functions for this version of Perl. Place them in &lt;code&gt;perl.sh&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;swap_perl&lt;/code&gt; to &lt;code&gt;perl.sh&lt;/code&gt;. Add a command to swap in the default version at the bottom of &lt;code&gt;perl.sh&lt;/code&gt;. Place &lt;code&gt;perl.sh&lt;/code&gt; in /etc/profile.d.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call &lt;code&gt;swap_perl&lt;/code&gt; in your process before executing Perl scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the shebang line of Perl scripts to use the &lt;code&gt;env&lt;/code&gt; command, which will search &lt;code&gt;PATH&lt;/code&gt; for the desired version of Perl.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;TPJ&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Listing 1
&lt;/h4&gt;

&lt;p&gt;Back to Article&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# -*- ksh -*-&lt;/span&gt;
&lt;span class="c"&gt;# =====================================================================&lt;/span&gt;
&lt;span class="c"&gt;# $Source: /home/cvs/repository/profiles/path_funcs.sh,v $&lt;/span&gt;
&lt;span class="c"&gt;# $Revision: 1.1 $&lt;/span&gt;
&lt;span class="c"&gt;# $Date: 2002/07/20 02:46:53 $&lt;/span&gt;
&lt;span class="c"&gt;# $Author: matthew $&lt;/span&gt;
&lt;span class="c"&gt;# $Name: $ - the cvs tag, if any&lt;/span&gt;
&lt;span class="c"&gt;# $State: Exp $&lt;/span&gt;
&lt;span class="c"&gt;# $Locker: $&lt;/span&gt;
&lt;span class="c"&gt;# =====================================================================&lt;/span&gt;

&lt;span class="c"&gt;##&lt;/span&gt;
&lt;span class="c"&gt;## Functions to manipulate paths safely&lt;/span&gt;
&lt;span class="c"&gt;##&lt;/span&gt;
&lt;span class="nv"&gt;PD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PERL_DEFAULT&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;/usr/bin/perl&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

addpath&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="c"&gt;## Get the path option. Figure out the pathvar and its value and&lt;/span&gt;
  &lt;span class="c"&gt;## pass both down to the Perl code. Why? Because if the pathvar is&lt;/span&gt;
  &lt;span class="c"&gt;## NOT exported, it does not end up in Perl %ENV and you will end&lt;/span&gt;
  &lt;span class="c"&gt;## up always redefining it instead of adding to it.&lt;/span&gt;

  &lt;span class="c"&gt;## Inits&lt;/span&gt;
  &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="nv"&gt;oarg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;

  &lt;span class="c"&gt;## Sharing OPTIND within a function call&lt;/span&gt;
  &lt;span class="nv"&gt;oldOPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTIND&lt;/span&gt;
  &lt;span class="nv"&gt;OPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s1"&gt;':hvp:fb'&lt;/span&gt; opt
  &lt;span class="k"&gt;do
    case&lt;/span&gt; &lt;span class="nv"&gt;$opt&lt;/span&gt; &lt;span class="k"&gt;in
      &lt;/span&gt;p &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;pvar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;
        &lt;span class="nb"&gt;eval &lt;/span&gt;&lt;span class="nv"&gt;pval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;
        &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-p &lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$pval&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;

      h &lt;span class="p"&gt;|&lt;/span&gt; v &lt;span class="p"&gt;|&lt;/span&gt; f &lt;span class="p"&gt;|&lt;/span&gt; b &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;oarg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$oarg&lt;/span&gt;&lt;span class="s2"&gt; -&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;done

  &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;$OPTIND&lt;/span&gt; - 1&lt;span class="sb"&gt;`&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    if&lt;/span&gt; &lt;span class="o"&gt;[!&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;pvar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
      &lt;span class="nb"&gt;eval &lt;/span&gt;&lt;span class="nv"&gt;pval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;
      &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-p &lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$pval&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="nb"&gt;shift
    &lt;/span&gt;&lt;span class="k"&gt;fi
  fi

  &lt;/span&gt;&lt;span class="nv"&gt;OPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$oldOPTIND&lt;/span&gt;

  &lt;span class="c"&gt;## We hardcode perl just incase we are trying to run swap_perl,&lt;/span&gt;
  &lt;span class="c"&gt;## which will take perl out of the PATH at some point before&lt;/span&gt;
  &lt;span class="c"&gt;## putting the new version in. The default in /usr/local/bin will&lt;/span&gt;
  &lt;span class="c"&gt;## be sufficient for this script.&lt;/span&gt;

  &lt;span class="c"&gt;## If you export PATH_FUNCS_DEBUG=-d, you get the debugger. -d:ptkdb&lt;/span&gt;
  &lt;span class="c"&gt;## works even better&lt;/span&gt;

  &lt;span class="nv"&gt;results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$PD&lt;/span&gt; &lt;span class="nv"&gt;$PATH_FUNCS_DEBUG&lt;/span&gt; &lt;span class="nt"&gt;-we&lt;/span&gt;&lt;span class="s1"&gt;'

##
## Options/arg processing section. Straight-forward
##
use Getopt::Std;

my %opts = ();
my @verbose = ();
my $usage = &amp;lt;&amp;lt;EOUSAGE;
Usage: addpath [-p] &amp;lt;pathvar&amp;gt; [-h] [-v] [-f|-b] &amp;lt;dirspec&amp;gt; [&amp;lt;dirspec&amp;gt; ...]
       Idempotently adds &amp;lt;dirspec&amp;gt; to &amp;lt;pathvar&amp;gt;
       -p specifies &amp;lt;pathvar&amp;gt;. -p is optional
       -h prints usage
       -v prints messages about the status of the command
       -f adds &amp;lt;dirspec&amp;gt; to front of &amp;lt;pathvar&amp;gt;
       -b adds &amp;lt;dirspec&amp;gt; to back of &amp;lt;pathvar&amp;gt;
EOUSAGE
;

## Process options
if (!getopts(q{hvp:fb},\%opts)) {
    die "$usage\n";
}

if ($opts{h}) {
    print STDERR "$usage\n";
    exit 0;
}

if(!defined($opts{p})) {
    die "No pathvar defined\n$usage\n";
}

if (defined($opts{f}) and defined($opts{b})) {
    die "-f and -b options are mutually exclusive\n$usage";
}

## Process args
if (!scalar(@ARGV)) {
    die "\nNo dirspec specified.\n$usage\n"
}

## Pull the pathvar and value out of the option
my $pathvar = undef;
my $pathval = undef;
($pathvar, $pathval) = split(/=/,$opts{p});

## $pathsep may be able to be pulled out of Config.pm on a per-platform
## basis. For now, default to UNIX.
my $pathsep=":";

## Hash-out the current sub-paths for easy comparison.
my %pathsubs=();
my $pathfront=0;
my $pathback=0;
if(!defined($pathval) ||
   !length($pathval)) {
    push @verbose, "$pathvar does not exist, initial assignment";
    $pathval = ""; ## Shuts up -w undef complaint later.
} else {
    %pathsubs = map { $_ =&amp;gt; $pathback++} split($pathsep,$pathval);
    $pathback--;
}

## Start checking each path arg
for my $argv (@ARGV) {

    ## This is a complete comparison, no need to take care
    ## of your path posssibly being a portion of an existing path.
    if(defined($pathsubs{$argv})) {
        push @verbose, "$argv already present in $pathvar";
    } else {
        ## Stick it where it belongs
        if(defined($opts{f})) {
            $pathsubs{$argv} = --$pathfront;
            push @verbose, "Pre-pended path $argv";
        } else {
            $pathsubs{$argv} = ++$pathback;
            push @verbose, "Appended path $argv";
        }
    }
}

## Put humpty dumpty back together again
$pathval = join ($pathsep,
                 sort {$pathsubs{$a} &amp;lt;=&amp;gt; $pathsubs{$b}} keys %pathsubs);

print STDERR join("\n",@verbose) if (defined($opts{v}));

## The shell will eval this:
print "$pathvar=$pathval";

'&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nv"&gt;$parg&lt;/span&gt; &lt;span class="nv"&gt;$oarg&lt;/span&gt; &lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;eval eval&lt;/span&gt; &lt;span class="nv"&gt;$results&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Back to Article&lt;/p&gt;

&lt;h4&gt;
  
  
  Listing 2
&lt;/h4&gt;

&lt;p&gt;Back to Article&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;delpath&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;## Get the path option. Figure out the pathvar and its value and&lt;/span&gt;
  &lt;span class="c"&gt;## pass both down to the Perl code. Why? Because if the pathvar is&lt;/span&gt;
  &lt;span class="c"&gt;## NOT exported, it does not end up in Perl %ENV and you will end&lt;/span&gt;
  &lt;span class="c"&gt;## up always redefining it instead of adding to it.&lt;/span&gt;

  &lt;span class="c"&gt;## Inits&lt;/span&gt;
  &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
  &lt;span class="nv"&gt;oarg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;

  &lt;span class="c"&gt;## Sharing OPTIND within a function call&lt;/span&gt;
  &lt;span class="nv"&gt;oldOPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTIND&lt;/span&gt;
  &lt;span class="nv"&gt;OPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s1"&gt;':hvp:en'&lt;/span&gt; opt
  &lt;span class="k"&gt;do
    case&lt;/span&gt; &lt;span class="nv"&gt;$opt&lt;/span&gt; &lt;span class="k"&gt;in
      &lt;/span&gt;p &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;pvar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;
        &lt;span class="nb"&gt;eval &lt;/span&gt;&lt;span class="nv"&gt;pval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;
        &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-p &lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$pval&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;

      h &lt;span class="p"&gt;|&lt;/span&gt; v &lt;span class="p"&gt;|&lt;/span&gt; e &lt;span class="p"&gt;|&lt;/span&gt; n &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;oarg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$oarg&lt;/span&gt;&lt;span class="s2"&gt; -&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="k"&gt;done

  &lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;expr&lt;/span&gt; &lt;span class="nv"&gt;$OPTIND&lt;/span&gt; - 1&lt;span class="sb"&gt;`&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    if&lt;/span&gt; &lt;span class="o"&gt;[!&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;pvar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
      &lt;span class="nb"&gt;eval &lt;/span&gt;&lt;span class="nv"&gt;pval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;
      &lt;span class="nv"&gt;parg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-p &lt;/span&gt;&lt;span class="nv"&gt;$pvar&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$pval&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="nb"&gt;shift
    &lt;/span&gt;&lt;span class="k"&gt;fi
  fi

  &lt;/span&gt;&lt;span class="nv"&gt;OPTIND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$oldOPTIND&lt;/span&gt;

  &lt;span class="c"&gt;## We hardcode perl just incase we are trying to run swap_perl,&lt;/span&gt;
  &lt;span class="c"&gt;## which will take perl out of the PATH at some point before&lt;/span&gt;
  &lt;span class="c"&gt;## putting the new version in. The default in /usr/local/bin will&lt;/span&gt;
  &lt;span class="c"&gt;## be sufficient for this script.&lt;/span&gt;

  &lt;span class="c"&gt;## If you export PATH_FUNCS_DEBUG=-d, you get the debugger. -d:ptkdb&lt;/span&gt;
  &lt;span class="c"&gt;## works even better&lt;/span&gt;

  &lt;span class="nv"&gt;results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$PD&lt;/span&gt; &lt;span class="nv"&gt;$PATH_FUNCS_DEBUG&lt;/span&gt; &lt;span class="nt"&gt;-we&lt;/span&gt;&lt;span class="s1"&gt;'

##
## Options/arg processing section. Straight-forward
##
use Getopt::Std;

my %opts = ();
my @verbose = ();
my $usage = &amp;lt;&amp;lt;EOUSAGE;
Usage: delpath [-p] &amp;lt;pathvar&amp;gt; [-h] [-v] [-e] [-n] &amp;lt;dirspec&amp;gt; [&amp;lt;dirspec&amp;gt; ...]
       Removes &amp;lt;dirspec&amp;gt; from &amp;lt;pathvar&amp;gt;
       -p specifies &amp;lt;pathvar&amp;gt;. -p is optional
       -h prints usage
       -v prints messages about the status of the command
       -e &amp;lt;dirspec&amp;gt; is used as a regexp
       -n removed non-existent directories from &amp;lt;pathvar&amp;gt;
EOUSAGE
;

## Process options
if (!getopts(q{hvp:en},\%opts)) {
    die "$usage\n";
}

if ($opts{h}) {
    print STDERR "$usage\n";
    exit 0;
}

if(!defined($opts{p})) {
    die "No pathvar defined.\n$usage\n";
}

## Process args
if (!scalar(@ARGV)) {
    die "\nNo dirspec specified.\n$usage\n"
}

# Pull the pathvar and value out of the option
my $pathvar = undef;
my $pathval = undef;
($pathvar, $pathval) = split(/=/,$opts{p});

## $pathsep may be able to be pulled out of Config.pm on a per-platform
## basis. For now, default to UNIX.
my $pathsep=":";

## Hash-out the current sub-paths for easy comparison.
my %pathsubs=();
my $pathfront=0;
my $pathback=0;
if(!defined($pathval) ||
   !length($pathval)) {
    push @verbose, "$pathvar does not exist, nothing to do";
    $pathval = ""; ## Shuts up -w undef complaint later.
    goto NOTHING_TO_DO;
} else {
    %pathsubs = map { $_ =&amp;gt; $pathback++} split($pathsep,$pathval);
    $pathback--;
}

## Start checking each path arg
for my $argv (@ARGV) {

    my @matches = ();
    my $msg = undef;
    if(defined($opts{e})) {
        $msg = '&lt;/span&gt;Regexp&lt;span class="s1"&gt;';
        @matches = grep {$_ =~ /$argv/} keys %pathsubs;
    } else {
        $msg = '&lt;/span&gt;Path&lt;span class="s1"&gt;';
        @matches = grep {$_ eq $argv} keys %pathsubs;
    }
    if(scalar(@matches)) {
        delete @pathsubs{@matches};
        push @verbose, "Deleted paths ", join(",",@matches);
    } else {
        push @verbose, "$msg $argv not found";
    }
}

## Check for empties
if(defined($opts{n})) {
    @matches = grep {! -d $_} keys %pathsubs;
    if(scalar(@matches)) {
        delete @pathsubs{@matches};
        push @verbose, "Deleted non-existent paths ", join(",",@matches);
    }
}

## Put humpty dumpty back together again
$pathval = join ($pathsep,
                 sort {$pathsubs{$a} &amp;lt;=&amp;gt; $pathsubs{$b}} keys %pathsubs);

NOTHING_TO_DO:
print STDERR join("\n",@verbose) if (defined($opts{v}));

## The shell will eval this:
print "$pathvar=$pathval";

'&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nv"&gt;$parg&lt;/span&gt; &lt;span class="nv"&gt;$oarg&lt;/span&gt; &lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;eval eval&lt;/span&gt; &lt;span class="nv"&gt;$results&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Back to Article&lt;/p&gt;

&lt;h4&gt;
  
  
  Listing 3
&lt;/h4&gt;

&lt;p&gt;Back to Article&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swap_perl&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;## Validate the version argument&lt;/span&gt;
  &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$to&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;5.6.1 &lt;span class="p"&gt;|&lt;/span&gt; 5.8.0 &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nv"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
          &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Your choices are 5.6.1 and 5.8.0. Bye."&lt;/span&gt;
       &lt;span class="k"&gt;return &lt;/span&gt;1
       &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
  &lt;span class="nb"&gt;shift&lt;/span&gt;

  &lt;span class="c"&gt;## Determine what version is to be swapped out and do so, if&lt;/span&gt;
  &lt;span class="c"&gt;## possible&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No PERL_CURRENT_VERSION defined to swap out. Continuing..."&lt;/span&gt;
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"initial"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Silently skip unsetting Perl"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
  &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$to&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Current Perl version is already &lt;/span&gt;&lt;span class="nv"&gt;$to&lt;/span&gt;&lt;span class="s2"&gt;. Exiting."&lt;/span&gt;
    &lt;span class="k"&gt;return
  else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Swapping out &lt;/span&gt;&lt;span class="nv"&gt;$PERL_CURRENT_VERSION&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

    &lt;span class="c"&gt;## Multiple levels of string interpolation simplify our job here...&lt;/span&gt;
    unset_perl_&lt;span class="nv"&gt;$PERL_CURRENT_VERSION&lt;/span&gt;
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Swapping in &lt;/span&gt;&lt;span class="nv"&gt;$to&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

  &lt;span class="c"&gt;## and here...&lt;/span&gt;
  set_perl_&lt;span class="nv"&gt;$to&lt;/span&gt;

  &lt;span class="c"&gt;## Any other argument given to the function is treated as a&lt;/span&gt;
  &lt;span class="c"&gt;## potential location for modules. You can add your own local&lt;/span&gt;
  &lt;span class="c"&gt;## libraries to the PERL5LIB variable by specifying the root&lt;/span&gt;
  &lt;span class="c"&gt;## directories as arguments after the version number.&lt;/span&gt;

  &lt;span class="nv"&gt;adds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[!&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$adds&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;then
    for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$adds&lt;/span&gt;
    &lt;span class="k"&gt;do
      &lt;/span&gt;add_perl5lib &lt;span class="nv"&gt;$i&lt;/span&gt;
    &lt;span class="k"&gt;done
  fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Back to Article&lt;/p&gt;

</description>
      <category>perl</category>
      <category>versions</category>
    </item>
    <item>
      <title>Donna</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Thu, 16 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/donna-3hdd</link>
      <guid>https://forem.com/matthewpersico/donna-3hdd</guid>
      <description>&lt;p&gt;(Note: This was originally posted on &lt;a href="https://matthewpersico.blogspot.com/2023/02/no-tears.html" rel="noopener noreferrer"&gt;Blogspot&lt;/a&gt;, referenced from &lt;a href="https://www.coxeandgraziano.com/obituaries/Donna-Persico?obId=27264961" rel="noopener noreferrer"&gt;Coxe and Graziano Funeral Home&lt;/a&gt;, where other people also commented on my wife’s life. It was picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.)&lt;/p&gt;

&lt;h1&gt;
  
  
  No Tears
&lt;/h1&gt;

&lt;p&gt;As we take my wife to her resting place today, no tears. That was her mantra over the past few weeks. She took that from her father, as it was what he said as he passed away almost nine years ago. Life is a gift; be grateful for the gifts you receive and do not lament the ones you do not. It’s what we teach our kids at Christmas.&lt;/p&gt;

&lt;p&gt;But as I listened to her say that to visitors over the past few weeks, it occurred to me that our lives are not only a gift to ourselves, but also a gift we give to others. And Donna was a generous gift giver.&lt;/p&gt;

&lt;p&gt;She was a class mother, a religion teacher, a Cub Scout Den Mother, a special ed classroom assistant. She was one half of what I believe to have been one of the most successful Presidencies of the Iona Preparatory School Mother’s Auxiliary. She was the Christmas Cookie Queen. She was a loving mom. And a loving wife. But perhaps her most precious gift was her advice. She was the most moral person I know. She would tell you the answer to your question, easy or difficult, no sugar coating, no worrying about losing your friendship with her honesty. In this crazy world of ours, her decision making process was simple:&lt;/p&gt;

&lt;p&gt;Was it hurtful?&lt;/p&gt;

&lt;p&gt;Was it helpful?&lt;/p&gt;

&lt;p&gt;Was it “right”?&lt;/p&gt;

&lt;p&gt;From advice for medical procedures to understanding peoples’ actions, we all looked to Donna for that guidance. And, sometimes, her best advice was not that which we sought, but that which she gave us when we didn’t ask.&lt;/p&gt;

&lt;p&gt;Life is a gift to each of us.&lt;/p&gt;

&lt;p&gt;Life is a gift to give to others.&lt;/p&gt;

&lt;p&gt;Be grateful for the gifts you get, which in this case are the memories of Donna.&lt;/p&gt;

&lt;p&gt;Do not lament the gifts we will not receive.&lt;/p&gt;

&lt;p&gt;No tears.&lt;/p&gt;

</description>
      <category>personal</category>
    </item>
    <item>
      <title>Three Little Numbers</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Thu, 11 Aug 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/three-little-numbers-5hhm</link>
      <guid>https://forem.com/matthewpersico/three-little-numbers-5hhm</guid>
      <description>&lt;p&gt;(Originally published 2022-08-11, picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.)&lt;/p&gt;

&lt;p&gt;If you follow me on &lt;a href="https://www.facebook.com/matthew.persico" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt; you may be wondering, “What’s up with all the&lt;a href="https://www.facebook.com/1538859698/posts/pfbid0pG3fRH6v1oDaV4xmRATfz8WusqQHhRxSMS5jwdp2tB42BNi1LzUEZ2DK9nD7dfRsl/?d=n" rel="noopener noreferrer"&gt;Strava&lt;/a&gt;posts?” Well, it all comes down to three little numbers.&lt;/p&gt;

&lt;p&gt;2&lt;/p&gt;

&lt;p&gt;9&lt;/p&gt;

&lt;p&gt;1&lt;/p&gt;

&lt;p&gt;All less than 10.&lt;/p&gt;

&lt;p&gt;But when you put them together…&lt;/p&gt;

&lt;p&gt;On May 13, I was putting the bathroom back together after having the floor re-tiled. On a whim, I decided to see what the scale would say when I stepped on it. I’m not normally a “scale person”. I judge my health by which hole on my belt I happen to be using this week. Now I knew I was getting up there because there we less and less unused holes, but I took my usual attitude of, “Yeah I need to do something; eventually, I’ll get around to it.”. Then I stepped on the scale.&lt;/p&gt;

&lt;p&gt;291.&lt;/p&gt;

&lt;p&gt;Two hundred and ninety one.&lt;/p&gt;

&lt;p&gt;Ok. I am no doctor, but that was the highest I have every weighed.&lt;/p&gt;

&lt;p&gt;I looked at that number and thought about the countless number of times in the past month, year, years I said to my self that I had to do something about my weight. But there was never any motivation to change habits, work at some exercise.&lt;/p&gt;

&lt;p&gt;But this time when I looked at that number, I realized that even if I had no regard for my own health (and I do have some regard), the person most likely to be affected by my dropping dead of a stroke or a heart attack was my wife, starting her third year of chemo, for whom &lt;em&gt;I&lt;/em&gt; am providing the health benefits. Therefore, I had to do something.&lt;/p&gt;

&lt;p&gt;I started with a simple plan - eat less, don’t eat between meals and walk for an hour a day. As I started to work out the details of this plan, I happened to run into this &lt;a href="https://www.youtube.com/watch?v=XFh8PoTa-40" rel="noopener noreferrer"&gt;West Wing video&lt;/a&gt;while going down a YouTube rabbit hole one night. It’s the scene where Leo McGarry is exit-interviewing Karen Larson, the admin who outed Leo’s rehab stint for pills and alcohol. The relevant dialogue starts at&lt;a href="https://youtu.be/XFh8PoTa-40?t=120" rel="noopener noreferrer"&gt;2:00&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Karen: “So, after six and a half years, you’re still not allowed to have a drink?”&lt;/p&gt;

&lt;p&gt;Leo: “The problem is I don’t want a drink; I want 10 drinks.”&lt;/p&gt;

&lt;p&gt;And that resonated with me: My name is Matthew Persico and I am a&lt;a href="https://en.wikipedia.org/wiki/Food_addiction" rel="noopener noreferrer"&gt;“foodaholic”&lt;/a&gt;. You see, when you want a cookie, you take &lt;em&gt;a&lt;/em&gt; cookie; I, on the other hand, take a half sleeve. While you get a slice of pizza, I eat three. You have a dish of pasta, I get a bowl, go back for seconds, and grab another spoonful as I am putting it into the fridge.&lt;/p&gt;

&lt;p&gt;I get a Twinkie at the gas station every time I fill up a car. I get a Snickers or Payday or Baby Ruth every time I check out at the grocery store.&lt;/p&gt;

&lt;p&gt;And when my wife goes to bed at 9pm, it’s showtime! Put on three hours of Star Trek, First commercial: the aforementioned half-sleeve of cookies. Next break, fruit. Next break, peanut butter and jelly sandwich. Next break, crackers. Next break, ice cream. And on, and on, and on.&lt;/p&gt;

&lt;p&gt;I do not mean to belittle anyone or minimize the issues and problems of anyone who has an actual medical diagnosis of addition; I am not medically qualified to make such diagnoses. But if I cannot control my intake of food and I do your worst consumption out of sight, that sounds to me like an addiction, no?&lt;/p&gt;

&lt;p&gt;So, what do you do? You cannot stop eating, right? Of course, but look at alcoholism: you can still drink, just not alcohol. That is the path I took: I can still eat, just not as much as I was eating and not everything that I was eating.&lt;/p&gt;

&lt;p&gt;I settled in on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Breakfast - One serving of cereal with skim milk, possibly fruit topped, or two eggs (with no more than three strips of bacon on Sundays).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lunch - Two or three slices of turkey, a slice of swiss and a 70-calorie wrap for lunch. Absolutely no mayo. I’ll use relish, pickles, mustard even cole slaw on occasion as garnishes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dinner - salad or steamed frozen vegetable plus whatever protein Donna wants - fish, chicken, steak, the occasional hamburger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dessert is one piece of fruit or a serving of cut berries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And. That’s. It.&lt;/p&gt;

&lt;p&gt;Between meals, I take my sodastream and drop in a lime. No eating between. And certainly not between dinner and breakfast. In order to pull of that last bit, I’ve been going to bed at the same time Donna does so that I am not downstairs to get tempted to nosh.&lt;/p&gt;

&lt;p&gt;Is it perfect? No. I tend to overeat on fruit and have more than one piece a day. Occasionally I’ll start watching Stat Trek or a Yankee game, but now with a difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First break: pickle slice wrapped in a slice of swiss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second break: If I can’t sit through the commercials without getting up to go to the fridge, I go upstairs and call it a night.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I haven’t had a slice of pizza, a dish of pasta, a bagel or a piece of regular bread in today-May13 days; you do the math. How is that possible? Surprisingly easy. I just ask myself this: “Is this piece of food going to sustain me or entertain me? If the latter, then is it worth dropping dead on my wife?”&lt;/p&gt;

&lt;p&gt;And the answer is always, “Of course not.” Look, I’ve eaten plenty of bagels, pizza, cake, cookies, etc. Was any of those items so memorable that I can recall it right now and say, “Wow. That &lt;em&gt;__&lt;/em&gt; was delicious!”?&lt;/p&gt;

&lt;p&gt;I’ve had recent occasion to talk to a bariatric nurse and a nutritionist that just got her masters. Both have said that true weight loss only works with lifestyle change and that in order to make that change, people typically need a breaking point. Maybe they got winded for the upteenth time climbing the stairs, or can’t keep up with their kids, or were the object of ridicule. In my case, it took my wife being sick to turn me around.&lt;/p&gt;

&lt;p&gt;And this &lt;em&gt;is&lt;/em&gt; a lifestyle change. Those meals I described above are pretty much how I have to eat until I die. Unless I am in the presence of company, either in my house or at someone else’s house or out at an occasion, that’s how I have to eat. Period. Save the sweets and the carbs for parties and celebrations only.&lt;/p&gt;

&lt;p&gt;So, if you’re still with me, you probably what to know what the result of all this walking, meal watching, and blogging is. Well, have a look:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Week&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Week Loss&lt;/th&gt;
&lt;th&gt;Total. Loss&lt;/th&gt;
&lt;th&gt;Week Avg. Loss&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;05/13&lt;/td&gt;
&lt;td&gt;291&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;05/20&lt;/td&gt;
&lt;td&gt;282&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;05/27&lt;/td&gt;
&lt;td&gt;277&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;7.0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;06/03&lt;/td&gt;
&lt;td&gt;274&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;5.6&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;06/10&lt;/td&gt;
&lt;td&gt;267&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;06/17&lt;/td&gt;
&lt;td&gt;263&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;5.4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;06/24&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;My flight back from Houston was on 6/25. Decided not to stress since I did enjoy myself a bit at the conference. Texas BBQ.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;07/01&lt;/td&gt;
&lt;td&gt;259&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;4.4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;07/08&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;07/15&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;4.4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;07/22&lt;/td&gt;
&lt;td&gt;243&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;4.8&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;07/29&lt;/td&gt;
&lt;td&gt;239&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;08/05&lt;/td&gt;
&lt;td&gt;237&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;4.5&lt;/td&gt;
&lt;td&gt;Veselka, Viniero’s and Yankee Stadium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;08/12&lt;/td&gt;
&lt;td&gt;234&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;4.4&lt;/td&gt;
&lt;td&gt;Three days of no walks due to weather, summer cold, 25 North Mac &amp;amp; Meat&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I’m down from waist size 48 to 38 and shirt size from teetering on the edge of 3XL down to an XL. I can walk long distances without strain (as long as the humidity is reasonable). I feel much more comfortable, have so much more energy and don’t loathe mirrors anymore. And, apparently, the Strava posts are serving as inspiration for two people I know to work on their own fitness.&lt;/p&gt;

&lt;p&gt;Most importantly, I’m much less likely to drop dead and leave my wife without insurance.&lt;/p&gt;

&lt;p&gt;So in the end, why am I writing? Because I am happy. Happy that I am healthier. Happy that I am no longer self conscious of pictures. Happy that I can look good. Why not share happiness with friends?&lt;/p&gt;

&lt;p&gt;&lt;a href="//../../../2016/08/24/2016-08-24-falling-off-the-wagon...and-getting-back-on-board"&gt;Prev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dieting</category>
    </item>
    <item>
      <title>Yet Another Perl Switch Statement</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Wed, 23 Mar 2022 15:56:58 +0000</pubDate>
      <link>https://forem.com/matthewpersico/yet-another-perl-switch-statement-54h3</link>
      <guid>https://forem.com/matthewpersico/yet-another-perl-switch-statement-54h3</guid>
      <description>&lt;p&gt;I am in the middle of a project at my job where we are converting some Perl to Python :-(. In the conversion I was explaining this invocation of a &lt;code&gt;switch&lt;/code&gt; statement:&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sr"&gt;/ARRAY/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;some_array_thing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="sr"&gt;/LIST/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;some_list_thing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;## default;&lt;/span&gt;
    &lt;span class="nv"&gt;some_scalar_thing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$thing&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;After explaining how the &lt;code&gt;for&lt;/code&gt; statement sets &lt;code&gt;$_&lt;/code&gt;, I was asked, "Why not just set &lt;code&gt;$_&lt;/code&gt;?"&lt;/p&gt;

&lt;p&gt;Indeed, why not? You can play with the following code here: &lt;a href="http://tpcg.io/KN9H82"&gt;http://tpcg.io/KN9H82&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="sr"&gt;/bar/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;we got bar&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="sr"&gt;/foo/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;we got foo&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="sr"&gt;/eek/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;we got eek&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;we dropped through&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;with output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;we got foo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, my questions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why have I never seen this in any discussion of Perl's &lt;code&gt;switch&lt;/code&gt; synonyms?&lt;/li&gt;
&lt;li&gt;Is there any inherent problem with this?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>switch</category>
    </item>
    <item>
      <title>Perl Lists - a Partial Taxonomy</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Tue, 25 May 2021 00:58:54 +0000</pubDate>
      <link>https://forem.com/matthewpersico/perl-lists-a-partial-taxonomy-g8p</link>
      <guid>https://forem.com/matthewpersico/perl-lists-a-partial-taxonomy-g8p</guid>
      <description>&lt;p&gt;&lt;a href="https://phoenixtrap.com/"&gt;Mark Garder&lt;/a&gt; recently published the article &lt;a href="https://phoenixtrap.com/2021/05/18/a-list-of-perl-list-processing-modules/"&gt;A list of Perl list processing modules&lt;/a&gt;, a detailed and factual, unopinionated listing of eight Perl modules that manipulate lists. So, naturally, when his factual, unopinionated listing was cross posted to &lt;a href="https://www.reddit.com/r/perl/comments/nfbhvt/a_list_of_perl_list_processing_modules/"&gt;Redit&lt;/a&gt;, the first comment was the emotional, highly opinionated: &lt;a href="https://www.reddit.com/r/perl/comments/nfbhvt/a_list_of_perl_list_processing_modules/gylv4co?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3"&gt;“So how do we go about fixing this mess? Because it is a mess.”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yes, the comment was mine.&lt;/p&gt;

&lt;p&gt;My intent was to see if we could create &lt;em&gt;One List:: To Rule Them All&lt;/em&gt;. Not only does it confuse people who want to learn Perl to have various list functions in different modules (and to have functions that share a name across modules work differently), but it also confuses Perl veterans. &lt;/p&gt;

&lt;p&gt;And yes, once again, that’s me.&lt;/p&gt;

&lt;p&gt;After some consideration, some education and a conversation with the &lt;a href="https://metacpan.org/author/PEVANS"&gt;current maintainer&lt;/a&gt; of &lt;a href="https://metacpan.org/pod/List::Util"&gt;List::Util&lt;/a&gt;, the module of list functions that come with Perl itself, it seemed to me that the first order of operations was to detail just how much of a “mess” this was. So, on Sunday afternoon, while waiting to go to the airport to pick up my son, and while watching Phil Mickelson winning the PGA championship at a record 50 years old, I put together the following spreadsheet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/11gI89kOJvm5b30jEWrLaL0D77sZnPKMhMeAP5WcFnzs/"&gt;https://docs.google.com/spreadsheets/d/11gI89kOJvm5b30jEWrLaL0D77sZnPKMhMeAP5WcFnzs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope that this can serve a as reference for people to see what's available and where it is available. Yes, it may not have a long shelf life,  but I learned a bit more about the state of the &lt;code&gt;List::&lt;/code&gt; namespace. Hopefully, you'll learn a bit too.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>lists</category>
      <category>arrays</category>
      <category>hashes</category>
    </item>
    <item>
      <title>Dad</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/dad-3e5e</link>
      <guid>https://forem.com/matthewpersico/dad-3e5e</guid>
      <description>&lt;p&gt;(Note: This was originally posted on &lt;a href="https://matthewpersico.blogspot.com/2020/08/thanks-dad.html" rel="noopener noreferrer"&gt;Blogspot&lt;/a&gt;, referenced from &lt;a href="https://www.sistofh.com/memorials/oreste-john-persico/4315106/obituary.php" rel="noopener noreferrer"&gt;Sisto Funeral Home&lt;/a&gt;, where other people also commented on my Dad’s life. It was picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.)&lt;/p&gt;

&lt;p&gt;Whenever I start a new job, inevitably, a few months in, someone asks me what my middle initial ‘O’ stands for. I tell them they should guess and, after about a week, when they’ve exhausted all their options, I let them off the hook:&lt;/p&gt;

&lt;p&gt;The ‘O’ is for Oreste.&lt;/p&gt;

&lt;p&gt;Oreste? How did you get that name?&lt;/p&gt;

&lt;p&gt;It’s my father’s.&lt;/p&gt;

&lt;p&gt;My father was born in 1942 in East Harlem, which, at the time, was a highly Italian enclave. The Italians followed the subway up from the lower east side and built a church on every corner. Kinda like Starbucks today.&lt;/p&gt;

&lt;p&gt;During his teens, my father had three momentous events happen to him. The first was getting moved out of East Harlem. He had lived there with a large set of aunts, uncles and cousins, but when Robert Moses decided that big, impersonal high rises were the epitome of “urban planning”, the lower class tenement dwellers all had to move someplace else. The family moved to various places on Long Island, with the exception of my father. He was going to All Hallows in the Bronx so that’s where they moved.&lt;/p&gt;

&lt;p&gt;The second momentous event was the death of his father. I don’t think my grandfather was around that much to begin with; then he died when my father was in high school. Here’s a sign-of-the-times side story for you: When my grandfather died, my grandmother went to the principal of All Hallows, who was, of course, a brother, to withdraw my father. When asked why, my grandmother said with her husband gone, she could no longer afford it. The principal told her not to pull her son out and not to concern herself with tuition.&lt;/p&gt;

&lt;p&gt;Can you imagine that happening today?&lt;/p&gt;

&lt;p&gt;My father only told me that very recently, like in the last five years or so. As I listened to him tell it, I realized that that event was precious and special to him and was one of the reasons he was so generous himself; paying it forward before that became a phrase. More about that later.&lt;/p&gt;

&lt;p&gt;The third momentous event in his teens was meeting my mother. A gang of friends was planning on going to one of the high school dances in the area and had arranged for my mother to be introduced to some guy. That guy either bailed or couldn’t make it so, someone grabbed my father instead. The rest, as they say, was history.&lt;/p&gt;

&lt;p&gt;Seven years later, the big guy with the blue, blue eyes married the skinny little guinea with the ravioli eyes. On June 14th – Flag Day. The big joke was “Raise the flag! Seven years, FINALLY they’re getting married!”&lt;/p&gt;

&lt;p&gt;A year and a half later, they had me. Four years later, my brother. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;My father went to Iona College after All Hallows. He was the last class to graduate from Iona as an all male school; women were admitted the next year. While he was there, he had a blast. He used to tell my grandmother stories of what they did in college but only years later when I was in my teens, and my grandmother was horrified. He was in the Glee Club. He sang. And partied.&lt;/p&gt;

&lt;p&gt;One trip in DC they decided to see how much furniture they could float in one of the tubs. And how much Tide it would take to fill up the Capitol fountain with bubbles. I heard stories of professor’s cars being moved to the large front steps of the college. Sideways. The removal and hiding of the dinosaur from the local gas station. And the appearance of a Bronx Zoo penguin in the fountains at Parkchester (sorry, Susan Chin, statute of limitations. 🙂 ). As my father would tell it, by senior year, the head brother of the college would simply call my father into his office and say, “Oreste, just fix it.” And of course not all the shenanigans were his fault. “Bro, it wasn’t me this time.” “Oreste, I don’t care. Just fix it.” Oh and he did graduate cum laude, I believe.&lt;/p&gt;

&lt;p&gt;But of all the stories he told me about college, the best was on that trip to DC. It was a competition and there were male and female glee clubs. One night the police were called about a riot in front of one of the hotels. Well it wasn’t a riot. My father got the brilliant idea to meet up his male glee club with one of the female clubs and re-enact scenes from West Side Story. They were just about into either the opening scene or Play It Cool or whatever and that’s when the cops showed up. Imagine my joy when my high school did West Side Story as the senior play. Thanks, Dad&lt;/p&gt;

&lt;p&gt;The music theme would play a large role in our lives. The radio station of choice in my house was WCBS FM. It’s where I learned harmonies – Sunday Night DooWoop Shop with Don K. Reed. And any time there was a road trip, we would sing all the way to wherever we were going. I learned to appreciate all sorts of music from Sinatra to Dion and the Belmonts to Broadway. I have a lifetime of appreciation of music from my father. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;My father, lacking guidance in his high school years, took a liberal arts degree. Which was about as useful then as it is now. In fact, until he got a car in maybe sophomore year, he frequently left the apartment, crossed over 95 (Bruckner Boulevard had just been sunk) and hitchhiked to college. After college, he moved up the ladder at the Grand Union he worked in to fund college. And then sometime in the early seventies, he wasn’t working there any more. I remember him driving a cab to make ends meet at all crazy hours. In fact, our neighbors Grace and Catello would lend us their dog Gino so that my mother felt safe without my father home at night. Now Gino, to my memory looked like a toy greyhound and wouldn’t scare anyone. But there he was in our living room, “protecting” us. While my father was out driving around trying to make ends meet. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;And then, at some point, my father decided to try his hand at selling cars. He ended up at Fordham Ford on Fordham Road across the street from the White Castle. The White Castle is still there; Fordham Ford is long gone. But when he told them his name, the manager there said, “Oreste? That’s not going to work in this business. You look like a Russell; your name is now Russ.” And to this day that’s how I can tell when you met my father. Pre-1973, you call him Orie. Post-1973, you call him Russ.&lt;/p&gt;

&lt;p&gt;And with that, my father began an almost 40 year career in the car business. The early years were some of the best. I was the only kid on the block whose family drove a new car every year. My father met up with two guys who turned out to be long time partners in crime, Ray DeBenedictis and Pete Mele. We’d end up at their houses on weekends, playing with their kids. They’d end up on junkets to Las Vegas because of the cars they’d sell and then enhance the junkets with tickets from “connections” that they had. I have Kodachrome slides of my mother’s purse on the stage where Elvis Presley was posing. My father even sang with a very young Michael Jackson when he heard my father doing harmonies.&lt;/p&gt;

&lt;p&gt;He was there when Dick Gidron opened his new Ford franchise to take over from Fordham Ford. It was a big deal; Gidron was one of the first and largest black franchisees. Lots of celebs there that night. No idea where I was, but I have pictures of my father between Muhammad Ali and Joe Frasier. I think it was Ali who looked at the arrangement and said, “Oooh – an Oreo cookie.”&lt;/p&gt;

&lt;p&gt;It was when Gidron Ford opened that my father came home one night and said, “Here. We need to stock the place with some inventory; pick colors and options.” So, we did. And we put a couple of crazy color combos in there. Don’t you know they got ordered anyway? Don’t you know they were some of the first cars sold?&lt;/p&gt;

&lt;p&gt;But it was my father’s experience with trying to find a job to support his family that made him, on many an occasion, drill into my head, “You don’t need a job; you need a career. Don’t make my mistake.” One of his fellow dealers had a son who worked at Texas Instruments, designing chips and writing software. It was the main influence on my going into electrical engineering. But when I was struggling with EE and wanted to switch to CompSci, he never said a disappointed word. All he wanted me to do is have a plan. He encouraged me to do what I needed to do. So I did. I switched to CompSci, graduated from Cooper Union, and have worked in Financial software for 33 years. and when I decided, in what now looks like a fit of stupidity, to try my hand a consulting, there was really only one name to choose: &lt;a href="https://www.facebook.com/OresteSoftwareInc/" rel="noopener noreferrer"&gt;https://www.facebook.com/OresteSoftwareInc/&lt;/a&gt; . Thanks, Dad.&lt;/p&gt;

&lt;p&gt;And thanks for all the things. We didn’t have a crazy-lot of stuff (that would come later, see Anthony’s first Christmas) but I never felt I was missing anything. Certainly not at Christmas. Sometimes he would get carried away. I remember one Christmas when he went out and bought me the three foot long spaceship from Space 1999. I was 14 years old the time; too old for such a toy. Or so I thought. I ended up playing with it and enjoying it very much. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;And then there was the organ. We were in Korvettes one day and I sat down at an organ on display and out of the complete blue/nowhere I stared playing music. Never played a keyboard in my life. One random act.&lt;/p&gt;

&lt;p&gt;Don’t you know, soon there was a two tiered organ with 12 sounds (and a headphone jack) delivered up two flights of stairs to our four room apartment? No birthday or anything, it just showed up. I played that thing for years. No lessons. But I got so much enjoyment out of that organ. Especially in 5th grade when I was home for weeks with the worst case of chicken pox Dr. Melfi had ever seen. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;My father worked very hard to make my life so much easier than his had been. Since he worked on Fordham Road and Bronx Science was only 15 minutes from Fordham Ford, he drove me, Frank Porco and Mark Rapacioli to school every morning for three years. Frank got a car senior year and returned the favor. The only time I ever took a bus &lt;em&gt;to&lt;/em&gt; school was for mid-terms and finals that were scheduled midday. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;And then, it was time to move. My mother’s parents had to leave their apartment, which was below ours on Edison Ave. Rather than let them leave on their own, my father got together with my grandfather. Grandpa put down the downpayment and my Dad would pick up the mortgage on a three family brick house on 197th street, a few blocks from where we lived. Not only did it give a place for my grandparents to live without worrying about renting anymore, it finally gave me and my brother separate rooms. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;It wasn’t easy. This was the early 80’s when interest rates were in the mid-teens. But my Dad had it all budgeted out on spreadsheets. No, not Excel. Literal. Green. Paper. Spreadsheets. He’d spread them out on the kitchen table to do bills and track budgets. Years later, under that influence, I’d become a Quicken devotee. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;So he’d come pretty far. He owned a house, he had two sons go through college and life was moving along quietly.&lt;/p&gt;

&lt;p&gt;And then came the grandkids.&lt;/p&gt;

&lt;p&gt;I was renting the top apartment with my wife, mom and dad were in the middle and my grandparents were in the bottom. My father would make it his business to drive my pregnant wife to work in Yonkers in bad weather because he didn’t want her dealing with the Yonkers hills. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;And then Anthony was born. Six months later, it was his first Christmas. Well, my father was in all his glory. When you have young adults around, you don’t really get to do silly things at Christmas. With a six month old, however…&lt;/p&gt;

&lt;p&gt;Now, I had asked my father not to go crazy with quantity and also with volume. The kid was only six months old. Most parents would have taken that as an honest request and complied.&lt;/p&gt;

&lt;p&gt;My father took it as a gauntlet thrown down.&lt;/p&gt;

&lt;p&gt;Let’s just say that when all was said and done, I took a picture of my black leather sofa COMPLETELY covered in toys. That made noise. And when I took that picture, my brother came upstairs to see… and promptly pushed every single one so that they all contributed to a hideous cacophony. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;By this time, my father was a manager in the car business. That meant you got two days off, instead of one, like salespeople got. Sunday was one of them. The other was NOT Saturday. In one particular location, his day off was Thursday. That meant of course, that he slept in and hung around the house, relaxing…&lt;/p&gt;

&lt;p&gt;No. Of course not. What did he do with his Thursdays? He spent them with the grandkids. He took them and my wife out to lunch. Every Thursday. And it was inevitable that they’d end up in at ToysRUs, which would be lighter by two Lego sets when they left. My sons to this day have fond memories of Papa Orie taking them to lunch and ToysRUs. I swear in another life, he must have been Santa Claus. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;Eventually, the many years of being overweight and smoking until 1984 took their toll. After his quad bypass, he retired. And when he found it getting hard to climb the stairs, my mother finally insisted that they move into the first floor apartment. So, instead of just moving in, he remodeled the place with a new bathroom and a new kitchen for my mom. Thanks, Dad.&lt;/p&gt;

&lt;p&gt;In retirement, my mother and father joined the local senior citizens center where there were promptly dubbed “The Kids.” And my father, in an act of combining years of managerial skills with his love of music, became the music director. I don’t know how many tons of paper were used in that center, but he was directing concerts at the rate of, I think, one every two months for a while. They were enjoying themselves. And us. And we them.&lt;/p&gt;

&lt;p&gt;But no story goes on forever. Over the past few years my father’s heart started wearing down. He lost his appetite and a lot of weight. He started slowing down. We noticed it at Christmas where sat at our table, but said nothing, just concentrating on eating.&lt;/p&gt;

&lt;p&gt;By February of this year, he wasn’t interested in getting up and out at all. Too cold. And then COVID hit. By July, we had to put him in the hospital and he ended up at Providence Rest for rehab. And then the dementia really set in. Endless days of only seeing my mom on a screen due to COVID really took their toll on his mental health.&lt;/p&gt;

&lt;p&gt;This afternoon my mom took a call. He had pneumonia. They wanted to send him to Einstein.&lt;/p&gt;

&lt;p&gt;We said no.&lt;/p&gt;

&lt;p&gt;Of all the things he did NOT want, he did not want to end up in a nursing home. Short term for rehab was one thing, but a long series of hospital/nursing home shuffles was not what he wanted.&lt;/p&gt;

&lt;p&gt;So we asked for palliative care to be administered, figuring with his kidneys and heart the way they were, he’d be lucky to last two weeks.&lt;/p&gt;

&lt;p&gt;He barely lasted two hours.&lt;/p&gt;

&lt;p&gt;By 2:30 pm we were called to come to Providence Rest. We signed in, got our temperatures taken, and were escorted to his room on the second floor. We sat and watched and held his hand and talked to him as the oxygen bag slowed. He looked peaceful. Not in any pain at all. And he didn’t really look old. Just tired.&lt;/p&gt;

&lt;p&gt;By 3:15, he was at peace.&lt;/p&gt;

&lt;p&gt;I remember my mom and brother telling him that it was ok to go, go see his mom, his dad, his sister.&lt;/p&gt;

&lt;p&gt;For my part, I leaned over to his ear and I thanked him. For a man that didn’t have a father for long and didn’t have the guidance he eventually gave to me and my brother, he sure as hell pieced it together pretty well. That’s what I told him:&lt;/p&gt;

&lt;p&gt;“You’ve done your duty as a husband and a father. You did it very well. Sleep easy.”&lt;/p&gt;

&lt;p&gt;“Thanks, Dad”&lt;/p&gt;

&lt;p&gt;Postscript: A few weeks after Dad had passed, I realized that I had already paid tribute to him, while he was alive; to wit: Oreste Software, Inc.&lt;/p&gt;

</description>
      <category>personal</category>
    </item>
    <item>
      <title>Falling Off The Wagon…and Getting Back On Board</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Wed, 24 Aug 2016 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/falling-off-the-wagonand-getting-back-on-board-1geh</link>
      <guid>https://forem.com/matthewpersico/falling-off-the-wagonand-getting-back-on-board-1geh</guid>
      <description>&lt;p&gt;(Originally published 2016-08-24, picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.)&lt;/p&gt;

&lt;p&gt;Yep, I fell off the wagon. After over a month of strict accounting for all the food I put into my body, I went on a food bender these past two days. Double portion of salmon for dinner. A bit too many fruits after dinner. Then a hearty Irish Stew for lunch with friends the next day, followed by more of too much fruit after dinner followed by 270 calories of Italian cookies and a chicken sandwich at 11:30pm. Ugh.&lt;/p&gt;

&lt;p&gt;I checked the scale and I gained two pounds since the last weigh-in. Now that’s not a lot, but when you’re losing a pound a day, who wants to hear about any gain?&lt;/p&gt;

&lt;p&gt;And these past two days of overeating have manifested themselves in how I felt this morning. Sluggish to get up. Tired. Flat. No energy.&lt;/p&gt;

&lt;p&gt;This is bad. Am I at risk of blowing my whole program?&lt;/p&gt;

&lt;p&gt;Nah.&lt;/p&gt;

&lt;p&gt;I went through my closet last night. I’m comfortably back into size 42 pants. 40’s were doable in a pinch. That means that instead of rotating the only two pairs of pants that fit me, I can now wear six, and they are all not black. I also have a lot more shorts I can wear, instead of just the three size 46’s I bought in a panic at this summer’s start. Considering that my goal is to get into 38, I’m not that far off.&lt;/p&gt;

&lt;p&gt;I have also re-affirmed that yes, I am a foodaholic. Now, did I Google that term for the exact definition? No. Does it trivialize the thousands (millions?) of people with acute addictions to alcohol, drugs, and food where they’re 400-600 pounds? Probably.&lt;/p&gt;

&lt;p&gt;But when I fail to keep my goal (size 38) in the forefront, when I am left alone in the kitchen at night with no one to “catch” me, when I have the opportunity to go to bed because I am yawning, when I am not hungry, when all those things are in place and yet I still decide to eat more than I need to, then I do have what I would consider an addiction to food.&lt;/p&gt;

&lt;p&gt;Or maybe, let’s just call me a “live to eat” person, not an “eat to live” person. It’s wired into my culture, upbringing, DNA. I can accept that fact as long as I don’t allow it to take over my entire life. I’ll be a calorie counter until the day I die. Ok. That’s a small price to pay to extend that day much further into the future.&lt;/p&gt;

&lt;p&gt;The bottom line is that I broke form for a day or so. Guess what? I’m not dead. I’m not 277 pounds again. I’m not appreciably different than the guy two days ago that was doing well with his quest to eat better. I am, however, still very different that the guy who was 277 at the start of this process with all those bad habits and no clue. So, I am relaxed. One day will not kill you. Do not be discouraged by an off day. “Pick yourself up, dust yourself off, start all over again.&lt;/p&gt;

</description>
      <category>dieting</category>
    </item>
    <item>
      <title>Diet Is A Four Letter Word</title>
      <dc:creator>Matthew O. Persico</dc:creator>
      <pubDate>Tue, 09 Aug 2016 00:00:00 +0000</pubDate>
      <link>https://forem.com/matthewpersico/diet-is-a-four-letter-word-1nff</link>
      <guid>https://forem.com/matthewpersico/diet-is-a-four-letter-word-1nff</guid>
      <description>&lt;p&gt;(Originally published 2016-08-09, picked up by dev.to in May 2026, after I connected my dev.to account to my blog's RSS feed.)&lt;/p&gt;

&lt;p&gt;Remember George Carlin’s “Seven Dirty Words” (SDWs)? The ones you can’t say on TV? Ever?&lt;/p&gt;

&lt;p&gt;Five of them were four letters. That makes them Four Letter Words.&lt;/p&gt;

&lt;p&gt;If you’re a sysadmin, “user” is a Four Letter Word (FLW. I abbreviate a lot because I’m a lazy FLW; more about that later.).&lt;/p&gt;

&lt;p&gt;Well, I would like to add “diet” to that list. I am thoroughly convinced that the LAST thing you should do if you want to lose weight is go on a diet. Why? Because I haven’t been on a diet for the last 21 days and I’ve lost 21 pounds. (Update: As of August 19, 2016, make that 39 days, 32.6 pounds.)&lt;/p&gt;

&lt;p&gt;I was 277 pounds (19.7857 stone for my Brexitted friends, 125.645 kilos for the rest of the civilized world), when I started a program at work (Bloomberg, LLP; a great place to spend 8 hours a day) called Incubator 14. It’s defined as a wellness program. Its mission is to make you think about all aspects of your life and change those that make you unhappy. So far we’ve been through the nutrition, diet, and exercise portions.&lt;/p&gt;

&lt;p&gt;Now, for those of you who know me, you know I have no head for all the kumbaya, psychobabble mumbo jumbo. Just give me the diet, please. So, of course, did they give me a diet? No. They started off with, “Just keep track of what you eat so you can present it to the dietician when you have your one on one meeting in week 3.”&lt;/p&gt;

&lt;p&gt;Week 3? What the hell (FLW, but not Dirty Word) am I supposed to do until then? Count calories? Actually put down on record what kind of crap (FLW, also not a Dirty Word) I eat? Well, I guess if I’m going to go to meet the dietician, I can’t go empty handed.&lt;/p&gt;

&lt;p&gt;And so, with the help of a FitBit app that was foisted upon me in March by Bloomberg, and which I used for exactly two days before I gave up on it as being too tedious (laziness rears it’s ugly head again), I started to count calories. And that’s when the magic happened.&lt;/p&gt;

&lt;p&gt;First of all, giving a geek a new app is like giving a three-year-old a drum at Christmas - it’s the only thing they’ll play with. I found that the lookup-by-name facility was really good. I found that the phone was tracking my steps and feeding it to the app; wow, I walk that far? And then I found the bar code scanner. OOOOOOOOH! I could type less.&lt;/p&gt;

&lt;p&gt;Second, a funny thing happens when you start counting calories; you start paying attention to exactly what it is you’re eating. You learn that a two-pack of Devil Dogs is 375 calories, whereas two cups of cut, frozen strawberries (about two handfuls) are only 114. 114? That’s all? Hmm. The jumbo eggs are only 90 each so a plain omelet is 270. That’s all? And that 1000+ calorie BigMac meal starts to look positively deadly. Unless it’s all you eat the whole day.&lt;/p&gt;

&lt;p&gt;What you find is that classic dieting advice such as shop around the edge of the supermarket, eat things as close to their state of living as possible, and portion control really work. I wasn’t on a diet. I was just counting calories. I wasn’t doing Atkins or South Beach or Grapefruit where I had to read a reference a book. I wasn’t paying Weight Watchers, Jenny Craig or anyone else to be my mother and cook (actually to process it into a preservative laden mess) for me.&lt;/p&gt;

&lt;p&gt;Nope. All I did was take a little technology and do what we learned in grade school - count. To be fair, when my watch fortuitously broke a week into the program, I figured it would be worth my while to replace it with a FitBit ChargeHR, which counted steps more accurately, factored in my actual heart rate to my calorie burn AND gave me extra credit for climbings stairs, so I am taking a bit MORE than “a little technology.’ But the first week of just using the phone was so encouraging, that it made me want to do better; hence the ChargeHR.&lt;/p&gt;

&lt;p&gt;Now, it helps if you’re OCD/fanatical about counting EVERY SINGLE THING YOU EAT. But, if you have the FitBit app, remember, it scans UPC codes. Bingo! Just adjust the portion size and off you go. Stuff like fruits, veggies, salads, and meats are all searchable. Just remember that a cup is about a handful and the weight of a deck of cards is 3.3 oz when cooking utensils and scales are not available.&lt;/p&gt;

&lt;p&gt;And you must be honest with yourself, Not counting that cake because it’s Saturday is a nice joke, but it’s not going to get you back into your favorite jeans any sooner.&lt;/p&gt;

&lt;p&gt;So, if you are looking in the mirror and you are not happy with the shape that you see, don’t diet. Start counting.&lt;/p&gt;

</description>
      <category>dieting</category>
    </item>
  </channel>
</rss>
