<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Laurent Dami</title>
    <description>The latest articles on DEV Community by Laurent Dami (@damil).</description>
    <link>https://dev.to/damil</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%2F1327331%2F93e2fefd-f601-4dd7-8017-97c0d465e0bd.jpg</url>
      <title>DEV Community: Laurent Dami</title>
      <link>https://dev.to/damil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/damil"/>
    <language>en</language>
    <item>
      <title>Beautiful Perl feature: "heredocs", multi-line strings embedded in source code</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Sat, 28 Mar 2026 20:14:33 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-heredocs-multi-line-strings-embedded-in-source-code-863</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-heredocs-multi-line-strings-embedded-in-source-code-863</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series. See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;Previous posts covered random topics ranging from fundamental concepts like &lt;a href="https://dev.to/damil/beautiful-perl-feature-blocks-2o4"&gt;blocks&lt;/a&gt; or &lt;a href="https://dev.to/damil/beautiful-perl-feature-two-sided-constructs-in-list-or-in-scalar-context-4fhd"&gt;list context and scalar context&lt;/a&gt; to sharp details like &lt;a href="https://dev.to/damil/beautiful-perl-feature-reusable-subregexes-4iib"&gt;reusable subregexes&lt;/a&gt;. Today's topic is neither very fundamental nor very sharp: it is just a handy convenience for managing multi-line strings in source code, namely the &lt;em&gt;heredoc&lt;/em&gt; feature. This is not essential, because multi-line strings can be expressed by other means; but it addresses a need that is quite common in programming, so it is interesting to compare it with other programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Heredocs": multi-line data embedded in source code
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Here_document" rel="noopener noreferrer"&gt;"here document"&lt;/a&gt;, abbreviated as "heredoc", is a piece of multi-line text &lt;em&gt;embedded in the source code&lt;/em&gt;. Perl borrowed the idea from Unix shells, and was later imitated by other languages like PHP or Ruby (discussed below). So instead of concatenating single lines, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$email_template&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dear %s,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You just won %d at our lottery!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;To claim your prize, just click on the link below.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;one can directly write the whole chunk of text, with a freely-chosen final delimiter, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$email_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="nv"&gt;_END_OF_MAIL_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;Dear&lt;/span&gt; &lt;span class="nv"&gt;%s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nv"&gt;You&lt;/span&gt; &lt;span class="nv"&gt;just&lt;/span&gt; &lt;span class="nv"&gt;won&lt;/span&gt; &lt;span class="nv"&gt;%d&lt;/span&gt; &lt;span class="nv"&gt;at&lt;/span&gt; &lt;span class="k"&gt;our&lt;/span&gt; &lt;span class="nv"&gt;lottery&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="nv"&gt;To&lt;/span&gt; &lt;span class="nv"&gt;claim&lt;/span&gt; &lt;span class="nv"&gt;your&lt;/span&gt; &lt;span class="nv"&gt;prize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;just&lt;/span&gt; &lt;span class="nv"&gt;click&lt;/span&gt; &lt;span class="nv"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nv"&gt;below&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="nv"&gt;_END_OF_MAIL_&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version is easier to write and to maintain, and also easier to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perl heredoc syntax
&lt;/h2&gt;

&lt;h3&gt;
  
  
  General rules
&lt;/h3&gt;

&lt;p&gt;A piece of "heredoc" data can appear anywhere in a Perl expression. It starts with an initial operator written either &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; or &lt;code&gt;&amp;lt;&amp;lt;~&lt;/code&gt;. The second variant with an added tilde &lt;code&gt;~&lt;/code&gt;, available since Perl v5.26, introduces an &lt;em&gt;indented heredoc&lt;/em&gt;, where initial spaces on the left of each line are automatically removed by the interpreter; thanks to this feature the inserted text can be properly indented within the Perl code, as illustrated in the example above. The amount of indent removed from each data line is determined by the indent of the final delimiter.&lt;/p&gt;

&lt;p&gt;The heredoc operator must be immediately followed by a &lt;em&gt;delimiter string&lt;/em&gt; freely chosen by the programmer. Lines below the current line will be part of the heredoc text, until the second appearance of that delimiter string which closes the heredoc sequence. The delimiter string can be any string enclosed in double quotes or in single quotes&lt;sup id="fnref1"&gt;1&lt;/sup&gt;; the double quotes can be omitted if the string would be valid as an identifier (if the string only contains letters, digits and underscores). Indeed, the most common practice is to use unquoted strings in capital letters, often surrounded by underscores - but there is no technical obligation to do so. &lt;/p&gt;

&lt;p&gt;When explicit or implicit double quotes are used for the delimiter string, the content of the heredoc text is subject to &lt;em&gt;variable interpolation&lt;/em&gt;, like for a usual double-quoted string, whereas with single quotes, no interpolation is performed.&lt;/p&gt;

&lt;p&gt;The heredoc content only starts at the line &lt;em&gt;after&lt;/em&gt; the &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; symbol; before that next line, the current line must properly terminate the current expression, i.e. close any open parentheses and terminate the current statement with a final &lt;code&gt;;&lt;/code&gt;. For example, it is perfectly legal (and quite common) to have heredoc data within a subroutine call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;htmlize_markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="nv"&gt;_END_OF_MARKDOWN_&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;# Breaking news&lt;/span&gt;

  &lt;span class="c1"&gt;## Perl remontada&lt;/span&gt;

  &lt;span class="nv"&gt;After&lt;/span&gt; &lt;span class="nv"&gt;many&lt;/span&gt; &lt;span class="nv"&gt;years&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;Perl&lt;/span&gt; &lt;span class="nv"&gt;bashing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;software&lt;/span&gt; &lt;span class="nv"&gt;industry&lt;/span&gt; 
  &lt;span class="nv"&gt;slowly&lt;/span&gt; &lt;span class="nv"&gt;rediscovers&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;beauty&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;Perl&lt;/span&gt; &lt;span class="nv"&gt;design&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;Many&lt;/span&gt; &lt;span class="nv"&gt;indicators&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; 
  &lt;span class="nv"&gt;_END_OF_MARKDOWN_&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arbitrary string as delimiter
&lt;/h3&gt;

&lt;p&gt;As stated above, the delimiter string can be &lt;em&gt;any string&lt;/em&gt;, even if it includes special characters or spaces, provided that the string is explicitly quoted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ordinary_liturgy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ite, missa est&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="nv"&gt;Kyrie&lt;/span&gt;
  &lt;span class="nv"&gt;Gloria&lt;/span&gt;
  &lt;span class="nv"&gt;Credo&lt;/span&gt;
  &lt;span class="nv"&gt;Sanctus&lt;/span&gt;
  &lt;span class="nv"&gt;Agnus&lt;/span&gt; &lt;span class="nv"&gt;dei&lt;/span&gt;
  &lt;span class="nv"&gt;Ite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;missa&lt;/span&gt; &lt;span class="nv"&gt;est&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Empty string as delimiter
&lt;/h3&gt;

&lt;p&gt;The delimiter string can also be .. an empty string! In that case the heredoc content ends at the next empty line; this is an elegant way to minimize noise around the data. I used it for example for embedding Template toolkit fragments in the &lt;a href="https://metacpan.org/release/DAMI/Array-PseudoScalar-1.02/source/t/02-template.t" rel="noopener noreferrer"&gt;test suite for my Array::PseudoScalar module&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;my&lt;/span&gt; &lt;span class="nv"&gt;$tmpl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Template&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"";&lt;/span&gt;
  &lt;span class="nv"&gt;$tmpl&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;"",&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;# 1st arg: reference to heredoc string&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; / &lt;/span&gt;&lt;span class="p"&gt;")&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nv"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;qr[^\s+FOO / BAR / BUZ$]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scalar .replace()&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

  &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"";&lt;/span&gt;
  &lt;span class="nv"&gt;$tmpl&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;"",&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;last&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;FOREACH&lt;/span&gt; &lt;span class="nv"&gt;member&lt;/span&gt; &lt;span class="nv"&gt;IN&lt;/span&gt; &lt;span class="nv"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;member&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;member&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# FOREACH %]&lt;/span&gt;

  &lt;span class="nv"&gt;like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;qr/size is 3/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;array .size&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or for &lt;a href="https://metacpan.org/release/DAMI/Lingua-Thesaurus-0.13/source/lib/Lingua/Thesaurus/Storage/SQLite.pm#L115" rel="noopener noreferrer"&gt;embedding SQL fragments in my Lingua::Thesaurus module&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dbh&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;term_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;dbh&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;rel_type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;rel_id&lt;/span&gt;      &lt;span class="nb"&gt;CHAR&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;is_external&lt;/span&gt; &lt;span class="nb"&gt;BOOL&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;foreign&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="s1"&gt;'t be used with fulltext, because '&lt;/span&gt;&lt;span class="n"&gt;docid&lt;/span&gt;&lt;span class="s1"&gt;'
  # is not a regular column that can be referenced
  my $ref_docid = $params-&amp;gt;{use_fulltext} ? &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt; : '&lt;/span&gt;&lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s1"&gt;';

  $dbh-&amp;gt;do(&amp;lt;&amp;lt;"");
    CREATE TABLE relation (
      lead_term_id  INTEGER NOT NULL $ref_docid,
      rel_id        CHAR    NOT NULL REFERENCES rel_type(rel_id),
      rel_order     INTEGER          DEFAULT 1,
      other_term_id INTEGER          $ref_docid,
      external_info CHAR
    );

  $dbh-&amp;gt;do(&amp;lt;&amp;lt;"");
    CREATE INDEX ix_lead_term  ON relation(lead_term_id);

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

&lt;/div&gt;



&lt;p&gt;While it is technically possible to write &lt;code&gt;my $content = &amp;lt;&amp;lt;~ "";&lt;/code&gt; for an indented heredoc ending with an empty string (notice the &lt;code&gt;~&lt;/code&gt;), this requires that the blank line at the end be indented accordingly. In that case the fact that the blank line is composed of initial indenting spaces followed by a newline character is not visible when reading the source code, so this is definitely not something to recommend!&lt;/p&gt;

&lt;h3&gt;
  
  
  Several heredocs on the same line
&lt;/h3&gt;

&lt;p&gt;Several heredocs can start on the same line, as in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@blogs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dbh&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;selectall_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="nv"&gt;END_OF_SQL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\n/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="nv"&gt;END_OF_BIND_VALUES&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nb"&gt;select&lt;/span&gt; &lt;span class="nv"&gt;d_publish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;
  &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;blog_entries&lt;/span&gt;
  &lt;span class="nv"&gt;where&lt;/span&gt; &lt;span class="nv"&gt;pseudo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;d_publish&lt;/span&gt; &lt;span class="nv"&gt;between&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
  &lt;span class="nv"&gt;END_OF_SQL&lt;/span&gt;
  &lt;span class="nv"&gt;chatterbox&lt;/span&gt;
  &lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mf"&gt;.01.2023&lt;/span&gt;
  &lt;span class="mf"&gt;30.06.2024&lt;/span&gt;
  &lt;span class="nv"&gt;END_OF_BIND_VALUES&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first heredoc is the SQL request, and the second heredoc is a piece of text containing the bind values; the &lt;code&gt;split&lt;/code&gt; operation on the first line transforms this text into an array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Perl mechanisms for multi-line strings
&lt;/h3&gt;

&lt;p&gt;Heredocs are not the only way to express multi-line strings in Perl. String concatenation in source code, as shown in the initial example of this article, is of course always possible, albeit not very practical nor elegant. Yet another way is to simply insert newline characters inside an ordinary quoted string, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$str1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;this is
            a multi-line string&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$str2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qq{and this
              is another multi-line string}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but in that case the indenting spaces at the beginning of each line are always part of the data. So Perl offers more that one way to do it, it is up to the programmer to decide what is most appropriate according to the situation.&lt;/p&gt;

&lt;p&gt;Perl's acceptance of literal newline characters inside ordinary quoted strings is sometimes very handy, and therefore was also adopted in PHP and Ruby; but the majority of other languages, like Java, JavaScript, Python and C++, do not allow it - this is why they needed to introduce other mechanisms, as we will see later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other programming languages
&lt;/h2&gt;

&lt;p&gt;As mentioned in the introduction, the idea of heredocs originated in Unix shells and later percolated into general-purpose programming languages. Some of them, inspired by Perl, adopted the shell-style heredoc syntax; other languages preferred the more familiar syntax of quoted strings, but with variants for supporting multi-line strings. This section will highlight the main differences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Languages with heredoc syntax
&lt;/h3&gt;

&lt;h4&gt;
  
  
  PHP
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc" rel="noopener noreferrer"&gt;syntax for heredocs in PHP&lt;/a&gt; is very close to Perl, except that it uses three less-than signs (&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;) instead of two (&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;). Like in Perl, the heredoc content is usually subject to variable interpolation, unless when the delimiter string is enclosed in single quotes; in that latter case, PHP uses the name "&lt;em&gt;nowdoc&lt;/em&gt;" instead of "heredoc".&lt;/p&gt;

&lt;p&gt;There are a couple of technical differences with Perl's heredocs, however:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the ending delimiter, even if enclosed in double or in single quotes, must be a proper identifier, not an arbitrary string - so it cannot contain space or special characters .. and obviously it cannot be an empty string!&lt;/li&gt;
&lt;li&gt;the  PHP expression is interrupted at line where the heredoc starts, and must be properly terminated &lt;em&gt;after the final heredoc delimiter&lt;/em&gt;. Here is an example from the official documentation:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;&amp;lt;&amp;lt;&amp;lt;END
a
  b
    c
END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'d e f'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the reader must mentally connect the lines before and after the heredoc to understand the structure of the complete expression, which might be difficult if the heredoc content spans over many lines.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ruby
&lt;/h4&gt;

&lt;p&gt;There is little to say about &lt;a href="https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html" rel="noopener noreferrer"&gt;heredocs in Ruby&lt;/a&gt;: they work almost exactly like in Perl, with the same syntax, the same variants regarding interpolation of variables or regarding indented content, and the same possibility to use arbitrary quoted strings (including the empty string) as delimiters. Multiple heredocs starting on the same line are also supported.&lt;/p&gt;

&lt;p&gt;There is however a minor difference in the interpretation of indented content: in presence of an indented heredoc, called "squiggly heredoc" in Ruby, the interpreter considers the &lt;em&gt;least indented line&lt;/em&gt; to be the basis for indentation; the number of spaces before the delimiter string is irrelevant. So in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;END&lt;/span&gt;&lt;span class="sh"&gt;
    foo
  bar
&lt;/span&gt;&lt;span class="no"&gt;       END&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the value is `"  foo\nbar\n" (two spaces before "foo", no spaces before "bar"). In Perl this would raise an exception because the indentation level is determined by the number of spaces &lt;em&gt;before the terminating delimiter string&lt;/em&gt; and it is illegal to have content lines with less spaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  Languages with quoted multi-line strings
&lt;/h3&gt;

&lt;p&gt;Expressing multi-line strings in source code is quite a common need, so programming languages that support neither heredocs nor literal newline characters inside ordinary quoted strings had to offer something. A commonly adopted solution is  &lt;em&gt;triple-quoted strings&lt;/em&gt; as special syntax for multi-line string literals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Python
&lt;/h4&gt;

&lt;p&gt;Python was probably the inventor of &lt;a href="https://docs.python.org/3/reference/lexical_analysis.html#triple-quoted-strings" rel="noopener noreferrer"&gt;triple-quoted strings&lt;/a&gt;. These solved two problems at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;embedded double-quote or single-quote characters need not be escaped&lt;/li&gt;
&lt;li&gt;embedded newline characters are accepted and retained in the string value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as shown in this example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;str = """this is a triple-quoted string
         with embedded "double quotes"
         and embedded 'single quotes'
         and also embedded newlines""";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Triple-quoted literals have no syntactic support for handling indented content, so in the example above, initial spaces at lines 2, 3 and 4 are part of the data. Removing indenting spaces must be explicitly performed at runtime, usually through the &lt;a href="https://docs.python.org/3/library/textwrap.html#textwrap.dedent" rel="noopener noreferrer"&gt;textwrap.dedent() function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like for regular string literals, interpolation of expressions within triple-quoted strings can be performed through a &lt;a href="https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals" rel="noopener noreferrer"&gt;&lt;code&gt;f&lt;/code&gt; prefix&lt;/a&gt;, a feature introduced in 2017 in Python 3.6.&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript
&lt;/h4&gt;

&lt;p&gt;Originally JavaScript had no support neither for multi-line strings nor for variable interpolation within string literals. Both features were simultaneously introduced in 2015 through the new construct of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" rel="noopener noreferrer"&gt;template literals&lt;/a&gt;: instead of single or double quotes, the string is enclosed in backticks, and it may contain newline characters and interpolated expressions of form &lt;code&gt;${...}&lt;/code&gt;. Those two behavioural aspects always come together, there are no syntactic variants for using them independently.&lt;/p&gt;

&lt;h4&gt;
  
  
  Java
&lt;/h4&gt;

&lt;p&gt;Java introduced triple-quoted strings as late as 2020, under the name &lt;a href="https://docs.oracle.com/en/java/javase/18/text-blocks/index.html" rel="noopener noreferrer"&gt;text blocks&lt;/a&gt;. The compiler automatically removes "incidental spaces", i.e. indentation spaces at the beginning of lines, and trailing spaces at the end of lines. This mechanism has no basic support for variable interpolation; if needed, programmers have to use other classes like &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html" rel="noopener noreferrer"&gt;MessageFormat&lt;/a&gt; or &lt;a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/StringSubstitutor.html" rel="noopener noreferrer"&gt;StringSubstitutor&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Today many programming tasks need to handle some polyglot aspects: besides the main source code, fragments of other languages must be included, like HTML, CSS, XML, SQL, templates, etc. Therefore the need to embed multi-line strings in the main source code is quite frequent.&lt;/p&gt;

&lt;p&gt;Surprisingly, some popular languages took a very long time before proposing that kind of feature, and it is not always possible to freely decide some options, like removing indentation or applying variable interpolation. By contrast, Perl always had a rich spectrum of mechanisms, including but not limited to heredoc documents. Various options can be chosen with great flexibility, allowing the programmer to be creative in crafting legible and elegant source code. Yet another example of Perl's beautiful features!&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;This score excerpt is taken from Luciano Berio's &lt;a href="https://en.wikipedia.org/wiki/Sinfonia_(Berio)" rel="noopener noreferrer"&gt;Sinfonia&lt;/a&gt;, written in 1968. In the third movement, Berio makes ample citations of Mahler's &lt;a href="https://en.wikipedia.org/wiki/Symphony_No._2_(Mahler)" rel="noopener noreferrer"&gt;Symphony N° 2&lt;/a&gt;, a kind of "musical heredoc" inside the new composition.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;a third possibility is to enclose the string in backticks, but this will not be covered here. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl feature: reusable subregexes</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Tue, 17 Mar 2026 20:25:35 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-reusable-subregexes-4iib</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-reusable-subregexes-4iib</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;Perl is famous for its &lt;em&gt;regular expressions&lt;/em&gt; (in short: &lt;em&gt;regexes&lt;/em&gt;): this technology had been known for a long time, but Perl was probably the &lt;strong&gt;first&lt;/strong&gt; general-purpose programming language to integrate them into the core. Perl also augmented the domain-specific sublanguage of regular expressions with a large collection of &lt;a href="https://metacpan.org/dist/perl/view/pod/perlre.pod#Extended-Patterns" rel="noopener noreferrer"&gt;extended patterns&lt;/a&gt;; some of these were later adopted by many other languages or products under the name "Perl-compatible regular expressions".&lt;/p&gt;

&lt;p&gt;The whole territory of regular expressions is a vast topic; today we will merely focus on one very specific mechanism, namely the ability to define &lt;em&gt;reusable subregexes&lt;/em&gt; within one regex. This powerful feature is an extended pattern not adopted yet in other programming languages, except those that rely on the &lt;a href="https://www.pcre.org/" rel="noopener noreferrer"&gt;PCRE library&lt;/a&gt;, a C library meant to be used outside of Perl, but with a regex dialect very close to Perl regexes. &lt;strong&gt;PHP&lt;/strong&gt; and &lt;strong&gt;R&lt;/strong&gt; are examples of such languages.&lt;/p&gt;
&lt;h2&gt;
  
  
  A glimpse at Perl extended patterns
&lt;/h2&gt;

&lt;p&gt;Among the extended patterns of Perl regular expressions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/dist/perl/view/pod/perlre.pod#(?PARNO)-(?-PARNO)-(?+PARNO)-(?R)-(?0)" rel="noopener noreferrer"&gt;recursive subpatterns&lt;/a&gt;. The matching process can &lt;em&gt;recurse&lt;/em&gt;, so it becomes possible to match nested structures, like parentheses nested at several levels. You may have read previously in several places (even in Perl's own &lt;a href="https://metacpan.org/dist/perlfaq/view/lib/perlfaq6.pod#How-do-I-match-XML,-HTML,-or-other-nasty,-ugly-things-with-a-regex?" rel="noopener noreferrer"&gt;FAQ documentation&lt;/a&gt;!) that regular expressions cannot parse HTML or XML ... but with recursive patterns this is no longer true!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metacpan.org/dist/perl/view/pod/perlre.pod#(?(condition)yes-pattern|no-pattern)" rel="noopener noreferrer"&gt;conditional expressions&lt;/a&gt;, where the result of a subpattern can determine where to branch for the rest of the match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These mechanisms are extremely powerful, but quite hard to master; therefore they are seldom written directly by Perl programmers. The syntax is a bit awkward, due to the fact that when extended expressions were introduced, the syntax for new additional constructs had to be carefully chosen so as to avoid any conflict with existing constructs. Fortunately, some CPAN modules like &lt;a href="https://metacpan.org/pod/Regexp::Common" rel="noopener noreferrer"&gt;Regexp::Common&lt;/a&gt; help to generate such regular expressions. Probably the most advanced of those is Damian Conway's &lt;a href="https://metacpan.org/pod/Regexp::Grammars" rel="noopener noreferrer"&gt;Regexp::Grammars&lt;/a&gt;, an impressive &lt;em&gt;tour de force&lt;/em&gt; able to compile recursive-descent grammars into Perl regular expressions! But grammars can also be written without any helper module: an example of a hand-written grammar can be seen in the &lt;a href="https://metacpan.org/dist/perl/view/pod/perldata.pod#Identifier-parsing" rel="noopener noreferrer"&gt;perldata documentation&lt;/a&gt;, describing how Perl identifiers are parsed.&lt;/p&gt;
&lt;h2&gt;
  
  
  The DEFINE keyword
&lt;/h2&gt;

&lt;p&gt;For this article we will narrow down to a specific construct at the intersection between recursive subpatterns and conditional expressions, namely the &lt;a href="https://metacpan.org/dist/perl/view/pod/perlre.pod#(DEFINE)" rel="noopener noreferrer"&gt;&lt;code&gt;DEFINE&lt;/code&gt;&lt;/a&gt; keyword for defining &lt;em&gt;named subpatterns&lt;/em&gt;. Just as you would split a complex algorithm into subroutines, here you can split a complex regular expression into subpatterns! The syntax is &lt;code&gt;(?(DEFINE)(?&amp;lt;name&amp;gt;pattern)...)&lt;/code&gt; . An insertion of a named subpattern is written as &lt;code&gt;(?&amp;amp;name)&lt;/code&gt; and can appear &lt;em&gt;before&lt;/em&gt; the definition. Indeed, good practice as recommended by &lt;a href="https://metacpan.org/dist/perl/view/pod/perlre.pod#(DEFINE)" rel="noopener noreferrer"&gt;perlre&lt;/a&gt; is to start the regex with the main pattern, including references to subpatterns, and put the &lt;code&gt;DEFINE&lt;/code&gt; part with definitions of subpatterns at the end.&lt;/p&gt;

&lt;p&gt;The following example, borrowed from &lt;a href="https://metacpan.org/dist/perl/view/pod/perlretut.pod#Defining-named-patterns" rel="noopener noreferrer"&gt;perlretut&lt;/a&gt;, illustrates the use of named subpatterns for parsing floating point numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="o"&gt;/^&lt;/span&gt; &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;osg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;int&lt;/span&gt;&lt;span class="p"&gt;)(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;dec&lt;/span&gt;&lt;span class="p"&gt;)?&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;dec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(?:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;eE&lt;/span&gt;&lt;span class="p"&gt;](?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;osg&lt;/span&gt;&lt;span class="p"&gt;)(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)?&lt;/span&gt;
 &lt;span class="err"&gt;$&lt;/span&gt;
 &lt;span class="p"&gt;(?(&lt;/span&gt;&lt;span class="nv"&gt;DEFINE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;osg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-+&lt;/span&gt;&lt;span class="p"&gt;]?)&lt;/span&gt;         &lt;span class="c1"&gt;# optional sign&lt;/span&gt;
   &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;\&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# integer&lt;/span&gt;
   &lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;dec&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;\.&lt;/span&gt;&lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;     &lt;span class="c1"&gt;# decimal fraction&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;DEFINE&lt;/code&gt; part doesn't consume any input, its sole role is to define the named subpatterns &lt;code&gt;osg&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;dec&lt;/code&gt;. Those subpatterns are referenced from the main pattern at the top of the regex. Subpatterns improve readability and avoid duplication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: detecting cross-site scripting attacks
&lt;/h2&gt;

&lt;p&gt;Let's put &lt;code&gt;DEFINE&lt;/code&gt; into practice for a practical problem: the goal is to prevent &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting" rel="noopener noreferrer"&gt;cross-site scripting attacks&lt;/a&gt; (abbreviated 'XSS') against web sites.&lt;/p&gt;

&lt;p&gt;XSS attacks try to inject executable code in the inputs to the web site. The web server might then store such inputs, without noticing that these are not regular user data; later, when displaying a new web page that integrates that data, the malicious code becomes part of the generated page and is executed by the browser. The &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html" rel="noopener noreferrer"&gt;OWASP cheat sheet&lt;/a&gt; lists various techniques for performing such attacks.&lt;/p&gt;

&lt;p&gt;Looking at the list, one can observe three main patterns for injecting executable javascript in an HTML page:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;within a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag;&lt;/li&gt;
&lt;li&gt;within event-handling attributes to HTML nodes or SVG nodes, e.g. &lt;code&gt;onclick=...&lt;/code&gt;,  &lt;code&gt;onblur=...&lt;/code&gt;, etc.;&lt;/li&gt;
&lt;li&gt;within hyperlinks to &lt;code&gt;javascript:&lt;/code&gt; URLs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attacks through the third pattern are the most pernicious because of a surprising aspect of the URL specification: it admits ASCII control characters or whitespace &lt;em&gt;intermixed with the protocol part of the URL&lt;/em&gt;! As a result, an URL with embedded tabs, newlines, null or space characters like &lt;code&gt;ja\tvas\ncript\x00:alert('XSS')&lt;/code&gt; is valid according to Web standards.&lt;/p&gt;

&lt;p&gt;Many sources about XSS prevention take the position that &lt;em&gt;input filtering&lt;/em&gt; is too hard, because of the large number of possible combinations, and therefore any approach based on regular expressions is doomed to be incomplete. Instead, they recommend approaches based on &lt;em&gt;output filtering&lt;/em&gt;, where any user data injected into a Web page goes through an encoding process that makes sure that the characters cannot become executable code. The weak point of such approaches is that malicious code can nevertheless be stored on the server side, which is not very satisfactory intellectually, even if that code is made inocuous.&lt;/p&gt;

&lt;p&gt;With the help of &lt;code&gt;DEFINE&lt;/code&gt;, we can adopt another approach: perform sophisticated input filtering that will catch most malicious attacks. Here is a regular expression that successfully detects all XSS attacks listed in the OWASP cheat sheet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$prevent_XSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qr/
 (                          # capturing group
     &amp;lt;script                  # embedded &amp;lt;script ...&amp;gt; tag
   |                          # .. or ..
     \b on\w{4,} \s* =        # event handler: onclick=, onblur=, etc.
   |                          # .. or ..
     \b                       # inline 'javascript:' URL, possibly mixed with ASCII control chars
     j (?&amp;amp;url_admitted_chars)
     a (?&amp;amp;url_admitted_chars)
     v (?&amp;amp;url_admitted_chars)
     a (?&amp;amp;url_admitted_chars)
     s (?&amp;amp;url_admitted_chars)
     c (?&amp;amp;url_admitted_chars)
     r (?&amp;amp;url_admitted_chars)
     i (?&amp;amp;url_admitted_chars)
     p (?&amp;amp;url_admitted_chars)
     t (?&amp;amp;url_admitted_chars) :
  )                         # end of capturing group

  (?(DEFINE)                # define the reusable subregex
    (?&amp;lt;url_admitted_chars&amp;gt; [\x00-\x20]* )  # 0 or more ASCII control characters or space
  )
/&lt;/span&gt;&lt;span class="nv"&gt;xi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;url_admitted_chars&lt;/code&gt; subpattern matches any sequence of ASCII control characters or space (characters between hexadecimal positions 00 and 20 in the ASCII table); that subpattern is inserted &lt;em&gt;after every single character&lt;/em&gt; of the &lt;code&gt;javascript:&lt;/code&gt; word, so it will detect all possible combinations of embedded tabs, newlines, null characters or other exotic sequences.&lt;/p&gt;

&lt;p&gt;All that remains to be done is to apply the &lt;code&gt;$prevent_XSS&lt;/code&gt; regex to all inputs; depending on your Web architecture, this can be implemented easily at the intermediate layers of &lt;a href="https://metacpan.org/pod/Catalyst" rel="noopener noreferrer"&gt;Catalyst&lt;/a&gt; or &lt;a href="https://metacpan.org/pod/Mojolicious" rel="noopener noreferrer"&gt;Mojolicious&lt;/a&gt;, or also at the level of &lt;a href="https://metacpan.org/pod/Plack" rel="noopener noreferrer"&gt;Plack middleware&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Needless to say, this approach is not a substitute, but rather a &lt;em&gt;complement&lt;/em&gt; to common output encoding techniques to enforce even better protection against XSS attacks.&lt;/p&gt;

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

&lt;p&gt;Even if many other programming languages have now included regular expressions features, Perl remains the king in that domain, with &lt;em&gt;extended patterns&lt;/em&gt; that open a whole new world of possibilities. With recursive patterns and with the &lt;code&gt;DEFINE&lt;/code&gt; feature, Perl regexes can implement recursive-descent grammars, and the &lt;a href="https://metacpan.org/pod/Regexp::Grammars" rel="noopener noreferrer"&gt;Regexp::Grammars&lt;/a&gt; module is here to help in using such functionalities. At a more modest level, the &lt;code&gt;DEFINE&lt;/code&gt; mechanism helps to reuse subpatterns in hand-crafted regexes. What a beautiful feature!&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;The image is an excerpt from Bach's fugue &lt;a href="https://fr.wikipedia.org/wiki/Pr%C3%A9lude_et_fugue_en_mi_majeur_(BWV_878)" rel="noopener noreferrer"&gt;BWV 878&lt;/a&gt; in the second book of the Well-Tempered Clavier. In these bars, the main theme is reused in &lt;em&gt;diminution&lt;/em&gt;, where the note durations are halved with respect to the original presentation. A nice musical example of a subpattern!&lt;/p&gt;

</description>
      <category>coding</category>
      <category>perl</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Beautiful Perl feature : two-sided constructs, in list or in scalar context</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Wed, 11 Mar 2026 20:18:41 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-two-sided-constructs-in-list-or-in-scalar-context-4fhd</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-two-sided-constructs-in-list-or-in-scalar-context-4fhd</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;Today's topic is about &lt;strong&gt;two-sided constructs&lt;/strong&gt; that behave differently when used in &lt;strong&gt;list context&lt;/strong&gt; or in &lt;strong&gt;scalar context&lt;/strong&gt;: this is a feature unique to Perl, often disconcerting for people coming from other programming backgrounds, but very convenient once you are used to it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The notion of context
&lt;/h2&gt;

&lt;p&gt;Natural languages are full of ambiguities, as can be seen with the well-known sentences &lt;a href="https://en.wikipedia.org/wiki/Time_flies_like_an_arrow;_fruit_flies_like_a_banana" rel="noopener noreferrer"&gt;"Time flies like an arrow; fruit flies like a banana"&lt;/a&gt;, where the same words are either nouns or verbs, depending on the &lt;em&gt;context&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Programming languages cannot afford to have ambiguities because the source code must be translatable into machine instructions in a predictable way. Therefore most languages have unambiguous syntactic constructs that can be parsed bottom-up without much complication. Perl has a different approach: some core operators - and also some user-written subroutines - have &lt;em&gt;two-sided meanings&lt;/em&gt;, without causing any ambiguity problem because the appropriate meaning is determined by the &lt;em&gt;context&lt;/em&gt; in which these operators are used.&lt;/p&gt;

&lt;p&gt;Technically Perl has three possible contexts: &lt;strong&gt;list&lt;/strong&gt; context, &lt;strong&gt;scalar&lt;/strong&gt; context and &lt;strong&gt;void&lt;/strong&gt; context; but the void context is far less important than the other two and therefore will not be discussed here. An example of a list context is &lt;code&gt;foreach my $val (1, 2, 3, 5, 8) {...}&lt;/code&gt;, where a list of values is expected within the parenthesis; an example of a scalar context is &lt;code&gt;if ($x &amp;lt; 10) {...}&lt;/code&gt; where a scalar boolean condition is expected within the parenthesis. Some of the common Perl idioms that depend on context are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;construct&lt;/th&gt;
&lt;th&gt;result in list context&lt;/th&gt;
&lt;th&gt;result in scalar context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;an array variable &lt;code&gt;@arr&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;members of the array&lt;/td&gt;
&lt;td&gt;number of array elements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the readline operator &lt;code&gt;&amp;lt;STDIN&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;list of all input lines&lt;/td&gt;
&lt;td&gt;the next input line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the glob operator &lt;code&gt;&amp;lt;*.pl&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;list of all files matching the pattern&lt;/td&gt;
&lt;td&gt;the next file that matches the pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;regular expression with the &lt;code&gt;/g&lt;/code&gt; flag for "global match"&lt;/td&gt;
&lt;td&gt;all strings captured by all matches&lt;/td&gt;
&lt;td&gt;boolean result of the next match attempt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the &lt;code&gt;localtime&lt;/code&gt; function&lt;/td&gt;
&lt;td&gt;list of numbers as seconds, minutes, hours, etc.&lt;/td&gt;
&lt;td&gt;a string like "Fri Mar  6 23:00:12 2026"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are just a few examples; read &lt;a href="https://metacpan.org/dist/perl/view/pod/perlfunc.pod" rel="noopener noreferrer"&gt;perlfunc&lt;/a&gt; and &lt;a href="https://metacpan.org/dist/perl/view/pod/perlop.pod" rel="noopener noreferrer"&gt;perlop&lt;/a&gt; for reference to many other context-sensitive constructs.&lt;/p&gt;

&lt;p&gt;The advantage of having two different but related meanings for the same construct is that it reduces the number of constructs to learn. For example just remember that a regex with a &lt;code&gt;/g&lt;/code&gt; flag is a global match, and Perl will "do the right thing" depending on where you use it; so given:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$regex_p_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qr( \b   # word boundary
                       p    # letter 'p'
                       \w+  # one or more word letters
                     )&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can either write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@words_starting_with_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/$regex_p_word/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&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;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/$regex_p_word/g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;do_something_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;# $&amp;amp; contains the matched string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reducing the number of constructs is quite helpful in a rich language like Perl where the number of core functions and operators is large; but of course it requires that programmers are at ease with the notion of context. Perl textbooks put strong emphasis on this aspect of the Perl culture: for example the &lt;a href="https://learning.oreilly.com/library/view/learning-perl-8th/9781492094944/" rel="noopener noreferrer"&gt;"Learning Perl" book&lt;/a&gt; starts the section on context by saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is the most important section in this chapter. In fact, it’s the most important section in the entire book. In fact, it wouldn’t be an exaggeration to say that your entire career in using Perl will depend upon understanding this section.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Context-sensitive constructs also contribute to make the source code more concise and focused on &lt;em&gt;what&lt;/em&gt; the programmer wanted to achieve, leaving aside the details; this is convenient when readers just need an overview of the code, for example when deciding whether to adopt a module or not, or when explaining an algorithm to a business analyst who doesn't know Perl (yes I did this repeatedly in my career, and it worked well - so don't tell me that Perl is not readable!).&lt;/p&gt;

&lt;p&gt;This is not to say that the details can always be ignored; of course the people in charge of maintaining the code need to be aware of all the implications of context-sensitive operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relationship between the list result and the scalar result
&lt;/h2&gt;

&lt;p&gt;For every context-sensitive construct, the results in list context and in scalar context must somehow be related; otherwise it would be incomprehensible. But what would be a sensible relationship between the two contexts?  Most Perl core constructs are built along one of those two patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the scalar result is a &lt;strong&gt;condensed&lt;/strong&gt; version of the list result, like the &lt;code&gt;@arr&lt;/code&gt; or &lt;code&gt;localtime&lt;/code&gt; examples in the table above;&lt;/li&gt;
&lt;li&gt;the scalar result is an &lt;strong&gt;iterator&lt;/strong&gt; on some implicit state, like the &lt;code&gt;&amp;lt;STDIN&amp;gt;&lt;/code&gt; or glob examples in the same table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the scalar result is a condensed version, more detailed information may nevertheless be obtained by other means: for example, although a regular expression match in scalar context just returns a boolean result, various details about the match (the matched string, its position, etc.) can be retrieved through global variables.&lt;/p&gt;

&lt;p&gt;When the scalar result is an iterator, it is meant to be called &lt;em&gt;several times&lt;/em&gt;, yielding a different result at each call. Depending on the iterator, a special value is returned at the end to indicate to the caller that the iteration is finished (usually this value is an &lt;code&gt;undef&lt;/code&gt;). This concept is quite similar to Python's &lt;a href="https://docs.python.org/3/tutorial/classes.html#generators" rel="noopener noreferrer"&gt;generator functions&lt;/a&gt; or JavaScript's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*" rel="noopener noreferrer"&gt;function* construct&lt;/a&gt;, except that each of the Perl core operators is specialized for one particular job (iterating on lines in a file, or on files in a directory, or on occurrences of a regex in some text). Such iterators are particularly useful for processing large data, because they operate lazily, one item at a time, without loading the whole data into memory.&lt;/p&gt;

&lt;p&gt;As an aside, let us note that unlike Python or JavaScript, Perl does not have a builtin construct for general-purpose iterators; but this is not really needed because iterators can be constructed through Perl's &lt;em&gt;closures&lt;/em&gt;, as beautifully explained in the book &lt;a href="https://hop.perl.plover.com/book/" rel="noopener noreferrer"&gt;Higher-Order Perl&lt;/a&gt; - quite an ancient book, but essential and still perfectly valid. There are also several CPAN modules that apply these techniques for easier creation of custom iterators;  &lt;a href="https://metacpan.org/pod/Iterator::Simple" rel="noopener noreferrer"&gt;Iterator::Simple&lt;/a&gt; is my preferred one.&lt;/p&gt;

&lt;p&gt;I said that the two patterns just discussed cover &lt;em&gt;most&lt;/em&gt; core constructs ... but there is an exception: the &lt;a href="https://metacpan.org/pod/perlop#Range-Operators" rel="noopener noreferrer"&gt;range operator &lt;code&gt;..&lt;/code&gt;&lt;/a&gt;, like the documentation says, is "really two different operators depending on the context", so the meanings in list context and in scalar context are not related to one another. This will be discussed in more detail in a future article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing your own context-sensitive subroutines or methods
&lt;/h2&gt;

&lt;p&gt;Context-sensitive operations are not limited to core constructs: any subroutine can invoke &lt;code&gt;wantarray&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt; to know in which context it is called so that it can adapt its behaviour. But this is only necessary in some very specific situations; otherwise Perl will perform an &lt;em&gt;implicit conversion&lt;/em&gt; which in most cases is perfectly appropriate and requires no intervention from the programmer - this will be described in the next section.&lt;/p&gt;

&lt;p&gt;In my own modules the places where I used &lt;code&gt;wantarray&lt;/code&gt; were for returning condensed information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;in &lt;a href="https://metacpan.org/pod/DBIx::DataModel" rel="noopener noreferrer"&gt;DBIx::DataModel&lt;/a&gt;, statement objects have an &lt;a href="https://metacpan.org/dist/DBIx-DataModel/view/lib/DBIx/DataModel/Doc/Reference.pod#sql()" rel="noopener noreferrer"&gt;sql&lt;/a&gt; method that in list context returns &lt;code&gt;($sql, @bind)&lt;/code&gt;, i.e. the generated SQL followed by the bind values. Here the default Perl conversion to scalar context would return the &lt;em&gt;last bind value&lt;/em&gt;, which is of no use to the caller, so the method explicitly returns just  &lt;code&gt;$sql&lt;/code&gt; when called in scalar context;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;in &lt;a href="https://metacpan.org/pod/Search::Tokenizer" rel="noopener noreferrer"&gt;Search::Tokenizer&lt;/a&gt;, the tokenizer called in list context returns a tuple &lt;code&gt;($term, length($term), $start, $end, $term_index)&lt;/code&gt;. When called in scalar context, it just returns the &lt;code&gt;$term&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implicit conversions
&lt;/h2&gt;

&lt;p&gt;When an expression is not context-sensitive, Perl may perform an implicit conversion to make the result fit the context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scalar value in list context
&lt;/h3&gt;

&lt;p&gt;If a scalar result is used in list context, the obvious conversion is to make it a singleton list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@array1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt; &lt;span class="c1"&gt;# converted to ("foo")&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the scalar is &lt;code&gt;undef&lt;/code&gt; or an empty string, this will still be a singleton list, not the same thing as an empty list: so in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@array2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# converted to (undef)&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@array3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;# initialized to ()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@array2&lt;/code&gt; is a true value because it contains one element, while &lt;code&gt;@array3&lt;/code&gt; contains no element and therefore is a false value.&lt;/p&gt;

&lt;h3&gt;
  
  
  List value in scalar context
&lt;/h3&gt;

&lt;p&gt;If a list value is used in scalar context, the initial members of the list are thrown away, and the context gets the last value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$scalar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;# converted to 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behaviour is consistent with the &lt;a href="https://en.wikipedia.org/wiki/Comma_operator" rel="noopener noreferrer"&gt;comma operator&lt;/a&gt; inherited from C.&lt;/p&gt;

&lt;p&gt;An array variable &lt;em&gt;is not the same thing as a list value&lt;/em&gt;. An array is of course treated as a list when used in list context, but in scalar context it just returns the size of the array (an integer value). So in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@countdown&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$should_start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@countdown&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$should_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# says "yes"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the array holds 4 members and therefore is true in scalar context; by contrast the mere list has value &lt;code&gt;0&lt;/code&gt; in scalar context and therefore is false:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;$should_start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$should_start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# says "no"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Programming languages without context-sensitive constructs
&lt;/h2&gt;

&lt;p&gt;Since context-sensitivity is a specialty of Perl, how do other programming languages handle similar situations? Simply by providing differentiated methods for each context! Let us look for example at the "global matching" use case, namely getting either a list of all occurrences of a regular expression in a big piece of text, or iterating over those occurrences one at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global match in JavaScript
&lt;/h3&gt;

&lt;p&gt;In Perl a global match of shape &lt;code&gt;$text =~ /$regex/g&lt;/code&gt; involves a string and a regex that are put together through the &lt;em&gt;binding operator&lt;/em&gt; &lt;code&gt;=~&lt;/code&gt;. In JavaScript, since there is no binding operator, regex matches are performed by method calls in either way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String" rel="noopener noreferrer"&gt;String class&lt;/a&gt; has methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match" rel="noopener noreferrer"&gt;match()&lt;/a&gt;, taking a regex as argument, returning an array of all matches;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll" rel="noopener noreferrer"&gt;matchAll()&lt;/a&gt;, taking a regex as argument, returning an iterator;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search" rel="noopener noreferrer"&gt;search()&lt;/a&gt;, taking a regex as argument, returning the character index of the first match (and therefore ignoring the &lt;code&gt;/g&lt;/code&gt; flag);&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp" rel="noopener noreferrer"&gt;RegExp class&lt;/a&gt; has methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec" rel="noopener noreferrer"&gt;exec()&lt;/a&gt;, taking a string as argument, returning a "result array" that contains the matched string, substrings corresponding to capture groups, and positional information. When the regex has the &lt;code&gt;/g&lt;/code&gt; flag for global match, the &lt;code&gt;exec()&lt;/code&gt; method can be called repeatedly, iterating over the successive matches;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test" rel="noopener noreferrer"&gt;test()&lt;/a&gt;, taking a string as argument, returning a boolean result.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The MDN documentation has a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions" rel="noopener noreferrer"&gt;good guide&lt;/a&gt; on regular expresssions in JavaScript. The purpose here is not to study these methods in detail, but merely to compare with the Perl API: in JavaScript the operations have explicit method names, but they are more numerous. The fact that method names are english words does not dispense from reading the documentation, because it cannot be guessed from the method names that &lt;code&gt;match()&lt;/code&gt; returns an array and &lt;code&gt;matchAll()&lt;/code&gt; returns an iterator!&lt;/p&gt;

&lt;h3&gt;
  
  
  Global match in Python
&lt;/h3&gt;

&lt;p&gt;Regular expressions in Python do not belong to the core language, but are implemented through the &lt;a href="https://docs.python.org/3/library/re.html#" rel="noopener noreferrer"&gt;&lt;code&gt;re&lt;/code&gt; module in the standard library&lt;/a&gt;. Matching operations are performed by calling functions in that module, passing a string and a regex as arguments, plus possibly some other parameters. Functions &lt;a href="https://docs.python.org/3/library/re.html#re.search" rel="noopener noreferrer"&gt;re.search()&lt;/a&gt;, &lt;a href="https://docs.python.org/3/library/re.html#re.match" rel="noopener noreferrer"&gt;re.match()&lt;/a&gt; and &lt;a href="https://docs.python.org/3/library/re.html#re.fullmatch" rel="noopener noreferrer"&gt;re.fullmatch()&lt;/a&gt; are variants for performing a single match; for global match, which is the subject of our comparison, there is no &lt;code&gt;/g&lt;/code&gt; flag, but there are specific methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/re.html#re.findall" rel="noopener noreferrer"&gt;re.findall()&lt;/a&gt;, taking a regex, a string and possibly some flags as arguments, returning a list of strings;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/re.html#re.finditer" rel="noopener noreferrer"&gt;re.finditer()&lt;/a&gt;, also taking a regex, a string and possibly some flags as arguments, returning an &lt;em&gt;iterator&lt;/em&gt; yielding &lt;a href="https://docs.python.org/3/library/re.html#re.Match" rel="noopener noreferrer"&gt;Match objects&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Thanks to context-sensitive operations, Perl expressions are often very concise and nevertheless convey to the hasty reader an overview of what is going on. Detailed comprehension of course requires an investment in understanding the notion of context, how it is transmitted from caller to callee, and how the callee can decide to give different responses according to the context. Newcomers to Perl may think that the learning effort is greater than in other programming languages ... but we have seen that in absence of context-sensitive operations, the complexity goes elsewhere, in a greater number of methods or subroutines for handling all the variant situations. So context-sensitivity is definitely a beautiful feature of Perl!&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;This is a side-by-side view of the &lt;a href="https://en.wikipedia.org/wiki/Victoria_Hall_(Geneva)" rel="noopener noreferrer"&gt;Victoria-Hall&lt;/a&gt;, the main concert hall in Geneva, where the stage holds either a full symphonic orchestra, or just a solo recital. Same place, different contexts!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;as stated in the official documentation, &lt;code&gt;wantarray&lt;/code&gt; is ill-named and should really be called &lt;code&gt;wantlist&lt;/code&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl feature : fat commas, a device for structuring lists</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Tue, 03 Mar 2026 22:39:28 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-fat-commas-a-device-for-structuring-lists-4n2o</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-fat-commas-a-device-for-structuring-lists-4n2o</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;Today's topic is a Perl construct called &lt;strong&gt;fat comma&lt;/strong&gt;, which is quite different from the trailing commas discussed in the &lt;a href="https://dev.to/damil/beautiful-perl-feature-trailing-commas-4504"&gt;last post&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fat comma: an introduction
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;fat comma&lt;/em&gt; in Perl is a construct that doesn't involve a typographic comma! Visually it consists of an expression followed by an arrow sign &lt;code&gt;=&amp;gt;&lt;/code&gt; and another expression. This is used in many contexts, the most common being for initializing hashes or for passing named parameters to subroutines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sr"&gt;y      =&amp;gt; 34,
            width  =&amp;gt; 20,
            height =&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;draw_shape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; 
           &lt;span class="s"&gt;coords&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s"&gt;color&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fat comma is semantically equivalent to a comma; the only difference with a regular comma is &lt;em&gt;purely syntactic&lt;/em&gt;: if the left-hand side is a string that begins with a letter or underscore and is composed only of letters, digits and underscores, then that string doesn't need to be enclosed in quotes. The example above took advantage of this feature, but it could as well have been written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;draw_shape&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; 
           &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;draw_shape&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This last variant has exactly the same technical meaning, but clearly it does not convey the same impression to the reader; so the fat comma is mainly a device for &lt;em&gt;improving code readability&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  More general usage
&lt;/h2&gt;

&lt;p&gt;Since Perl does not impose many constraints, fat commas can be used in many other ways than just initializing hashes or passing named parameters to subroutine calls:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;they can appear at any place where a list is expected;&lt;/li&gt;
&lt;li&gt;they need not be only in pairs: triplets, quadruplets, etc. are allowed;&lt;/li&gt;
&lt;li&gt;mixtures of fat commas and regular commas are allowed (and even frequent);&lt;/li&gt;
&lt;li&gt;the expression on the left-hand side of a fat comma need not be a string - it can be any value.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most of these points are excellently illustrated in a collection of examples designed in 2017 by Sinan Ünür. Here is an excerpt from his answer to a &lt;a href="https://stackoverflow.com/questions/44037222/in-perl-when-would-you-use-a-fat-comma-key-value-syntax-in-a-literal-and-not-in" rel="noopener noreferrer"&gt;StackOverflow question asking when to use fat comma if not for hashes&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any time you want to automatically quote a bareword to the left of a fat comma:&lt;/p&gt;


&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-lh&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;or&lt;/p&gt;


&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;p&gt;Any time you think it makes the code easier to see&lt;/p&gt;


&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;@data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Any time you want to say "into":&lt;/p&gt;


&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;bless&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In short, &lt;code&gt;=&amp;gt;&lt;/code&gt; is a comma, plain and simple. You can use it anywhere you can use a comma. E.g.:&lt;/p&gt;


&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;# invoke f($x) (for its side effects) and g($y)&lt;/span&gt;
                        &lt;span class="c1"&gt;# assign the result of g($y) to $z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Fat commas for domain-specific languages
&lt;/h2&gt;

&lt;p&gt;A number of CPAN modules took advantage of fat commas for designing domain-specific languages (DSLs), exploiting the fact that fat commas can be used liberally for other purposes than just expressing pairs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moose
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Attribute declarations
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://metacpan.org/pod/Moose" rel="noopener noreferrer"&gt;Moose&lt;/a&gt; is the most well-known object-oriented framework for Perl; it also influenced several competing frameworks&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. Here is a short excerpt from the synopsis, showing a class declaration:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;package&lt;/span&gt; &lt;span class="nv"&gt;Point&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;Moose&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example where the fat comma does not introduce a pair of values, but rather a longer list in which the first element (the attribute name) is deliberately emphasized. Technically this &lt;code&gt;x&lt;/code&gt; attribute could have been declared as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;has&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isa&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;is&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with exactly the same result, but much less readability. Observe that in addition to the fat comma, the recommended Moose syntax also takes advantage here of two other Perl features, namely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the fact that a subroutine can be treated like a list operator&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, without parenthesis around the arguments: so the call &lt;code&gt;has 'x' =&amp;gt; ...&lt;/code&gt; is technically equivalent to &lt;code&gt;has('x' =&amp;gt; ...)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;the fact that a list within another list is &lt;em&gt;flattened&lt;/em&gt;, so the parenthesis in &lt;code&gt;'x' =&amp;gt; (isa =&amp;gt; 'Int', ...)&lt;/code&gt; are technically not necessary; they are present just for stylistic preference.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may have noticed that the single quotes around the attribute name are technically unnecessary: the &lt;code&gt;x&lt;/code&gt; attribute name could go unquoted in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;  &lt;span class="nv"&gt;has&lt;/span&gt; &lt;span class="s"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;isa&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rw&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here again it's a matter of stylistic preference; in this context I suppose that the Moose authors wanted to emphasize the difference between the subroutine name &lt;code&gt;has&lt;/code&gt; and the string &lt;code&gt;x&lt;/code&gt; passed as first argument.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subtype declarations
&lt;/h4&gt;

&lt;p&gt;Another domain-specific language in Moose is for declaring &lt;em&gt;types&lt;/em&gt;. The &lt;a href="https://metacpan.org/pod/Moose::Cookbook::Basics::Company_Subtypes" rel="noopener noreferrer"&gt;cookbook&lt;/a&gt; has this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Moose::Util::&lt;/span&gt;&lt;span class="nv"&gt;TypeConstraints&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Locale::&lt;/span&gt;&lt;span class="nv"&gt;US&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$STATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Locale::&lt;/span&gt;&lt;span class="nv"&gt;US&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;subtype&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USState&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="s"&gt;Str&lt;/span&gt;
    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;where&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="p"&gt;(&lt;/span&gt;    &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$STATES&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;code2state&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt; &lt;span class="nb"&gt;uc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
             &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$STATES&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;state2code&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt; &lt;span class="nb"&gt;uc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here again, fat commas and subroutine calls expressed as list operators were cleverly combined to form an expressive DSL for declaring Moose types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mojo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://metacpan.org/pod/Mojolicious" rel="noopener noreferrer"&gt;Mojolicious&lt;/a&gt; is one of the major Web frameworks for Perl. It uses a domain-specific language for declaring the &lt;em&gt;routes&lt;/em&gt; supported by the Web application; here are some excerpts from the &lt;a href="https://metacpan.org/pod/Mojolicious::Routes::Route" rel="noopener noreferrer"&gt;documentation&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;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;'}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;qr/\w+/&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;qr/Firefox/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(['&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;']&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:foo&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;($c) {&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Through these many variants we see a flexible language for declaring routes, where fat commas are used to visually convey some idea of structure within the lists of arguments. Observe that lines 3 and following are not pairs, but &lt;em&gt;triplets&lt;/em&gt;, and that the last line has an &lt;em&gt;arrayref&lt;/em&gt; (not a string!) to the left of the fat comma.&lt;/p&gt;

&lt;h2&gt;
  
  
  A word of caution about the quoting mechanism
&lt;/h2&gt;

&lt;p&gt;Let's repeat the syntactic rule: &lt;em&gt;if the left-hand side of the fat comma is a string that begins with a letter or underscore and is composed only of letters, digits and underscores, then that string doesn't need to be enclosed in quotes&lt;/em&gt;. We have seen numerous examples above that relied on this rule for more elegance and readability. One has to be careful, however, that builtin functions or user-defined subroutines could inadvertently be interpreted as strings instead of the intended subroutine calls. For example consider this snippet:&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;constant&lt;/span&gt; &lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tac&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;build_hash&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;shift&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;toe&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;789&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;build_hash&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;tic&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One could easily expect that the value of &lt;code&gt;$h&lt;/code&gt; is &lt;code&gt;{tic =&amp;gt; 123, tac =&amp;gt; 456, toe =&amp;gt; 789}&lt;/code&gt; ... but actually the result is &lt;code&gt;{foo =&amp;gt; 456, shift =&amp;gt; 123, toe =&amp;gt; 789}&lt;/code&gt;, because both &lt;code&gt;shift&lt;/code&gt; and &lt;code&gt;foo&lt;/code&gt; were interpreted here as mere strings instead of subroutine calls. The ambiguity can be resolved easily, either by putting an empty argument list after the subroutine calls, or by enclosing them in parenthesis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;build_hash&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;toe&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;789&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
 &lt;span class="c1"&gt;# or: return {(shift) =&amp;gt; 123, (foo) =&amp;gt; 456, toe =&amp;gt; 789};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some people would perhaps argue that the Perl interpreter should automatically detect that &lt;code&gt;shift&lt;/code&gt; or &lt;code&gt;foo&lt;/code&gt; are subroutine names ... but that would introduce too much fragility. The interpreter would then be dependent on the list of builtin Perl functions, and also be dependent on the list of symbols declared at that point in the code; future evolutions on either side could easily break the behaviour. So Perl's design, that blindly applies the syntactic rule formulated above, is much wiser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Similar constructs in other languages
&lt;/h2&gt;

&lt;p&gt;To my knowledge, no other programming language has a &lt;em&gt;general-purpose&lt;/em&gt; comma operator comparable to Perl's fat comma. What is quite common, however, is to have specific syntax for hashes (or "objects" or "dictionaries" or "records", as they are called in other languages), and sometimes specific syntax for named parameters in subroutine calls or method calls. This chapter explores some aspects on these directions.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript
&lt;/h3&gt;

&lt;h4&gt;
  
  
  JavaScript Objects
&lt;/h4&gt;

&lt;p&gt;The equivalent of a Perl hash is called  "object" in JavaScript; it is initialized as follows (example copied from the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_objects" rel="noopener noreferrer"&gt;MDN documentation&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nx"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// property name may be an identifier&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or a number&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;property n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or a string&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the syntax is &lt;code&gt;:&lt;/code&gt; instead of &lt;code&gt;=&amp;gt;&lt;/code&gt;&lt;sup id="fnref3"&gt;3&lt;/sup&gt;. Like in Perl, any quoted string can be used as a property name, or a number, or an unquoted string if that string can be parsed as an identifier. What is not allowed, however, is to use an &lt;em&gt;expression&lt;/em&gt; on the left-hand side: &lt;code&gt;{(2+2): value}&lt;/code&gt; or &lt;code&gt;{compute_name(): value}&lt;/code&gt; are syntax errors. The workaround for using expressions as property names is to first create the object, and then assign properties to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;            &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;compute_name&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Named parameters
&lt;/h4&gt;

&lt;p&gt;JavaScript has no direct support for passing named parameters to subroutines; however there is of course an indirect way, which is to pass an object to the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;show_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has id &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;show_user&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recent versions of JavaScript have a more sophistictated way of exploiting the object received as parameter: rather than grabbing successive properties into the object, the receiving function could instead use &lt;em&gt;object destructuring&lt;/em&gt; to extract the values into local lexical variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;show_user_v2&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has id &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;show_user_v2&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique can go even further by supplying default values to the lexical variables - an advanced technique described in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring#object_destructuring" rel="noopener noreferrer"&gt;MDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Dictionaries
&lt;/h4&gt;

&lt;p&gt;In Python the closest equivalent of a Perl hash is called a "dictionary". Like in JavaScript, dictionaries are initialized with list of keys and values separated by &lt;code&gt;:&lt;/code&gt;, enclosed in curly braces :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But unlike in JavaScript or Perl, keys on the left of the &lt;code&gt;:&lt;/code&gt; separator are &lt;em&gt;not quoted automatically&lt;/em&gt;: they are just ordinary expressions. This requires more typing from the programmer, but makes it possible to use operators or function calls, like in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;double&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;world&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;foobar&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;doubled&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# prints : {'helloworld': 11, 234: 'foobar', 6: 'doubled'}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Keyword arguments
&lt;/h4&gt;

&lt;p&gt;In Python, named parameters are called &lt;a href="https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments" rel="noopener noreferrer"&gt;keyword arguments&lt;/a&gt;. The syntax is different from dictionary initializers: the symbol &lt;code&gt;=&lt;/code&gt; is used to connect keywords to their values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;draw_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the left-hand side does not need to be quoted; but it must obey the &lt;a href="https://docs.python.org/3/reference/lexical_analysis.html#names-identifiers-and-keywords" rel="noopener noreferrer"&gt;syntax rules for identifiers&lt;/a&gt;, which means for example that strings containing spaces are not eligible. &lt;/p&gt;

&lt;p&gt;The construct of functions with keyword arguments is clearly different from the construct of dictionaries. They can be combined, however: a dictionary can be &lt;a href="https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists" rel="noopener noreferrer"&gt;unpacked&lt;/a&gt; as a list of key-value pairs to be passed as arguments to a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;x2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;draw_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but unlike in Perl or JavaScript, if the dictionary contains &lt;em&gt;other keys&lt;/em&gt; than those expected by the function, an exception is raised ("got an unexpected keyword argument"). This is beneficial for defensive programming, where the interpreter exerts more control, but at the detriment of flexibility, because a dictionary received from an external source (for example a config file or an HTTP request) must be filtered before it can be flattened and passed to the called function.&lt;/p&gt;

&lt;h3&gt;
  
  
  PHP
&lt;/h3&gt;

&lt;p&gt;PHP uses the &lt;code&gt;=&amp;gt;&lt;/code&gt; notation for key-value pairs in associative arrays, like in Perl, but without the automatic quoting feature. Therefore keys must be enclosed in double quotes or single quotes, like in Python. &lt;/p&gt;

&lt;p&gt;In addition, PHP &lt;em&gt;also uses the same notation&lt;/em&gt; &lt;code&gt;=&amp;gt;&lt;/code&gt; for anonymous functions, like in JavaScript, except that the &lt;code&gt;fn&lt;/code&gt; keyword must also be present.&lt;/p&gt;

&lt;p&gt;Here is an example where the two features are combined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$array1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
           &lt;span class="s2"&gt;"fun"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an associative array (like a Perl hash) where the key &lt;code&gt;foo&lt;/code&gt; is associated to value &lt;code&gt;"bar"&lt;/code&gt;, and the key &lt;code&gt;fun&lt;/code&gt; is associated with a function that returns another function. So beware when visually parsing a &lt;code&gt;=&amp;gt;&lt;/code&gt; in a PHP program!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The Perl construct of fat commas is very simple, with coherent syntax and semantics, and applicable in a wide range of situations. It helps to write readable code by allowing the programmer to structure lists and emphasize some relations between values in the list. This capability is often used to design domain-specific sublanguages within Perl. A beautiful construct indeed!&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;The picture shows the coupling mechanism on an old pipe organ. The french word for this is "accouplement", which in other contexts also means "mating"! &lt;/p&gt;

&lt;p&gt;When the mechanism is activated, notes played on the lower keyword also trigger the notes on the upper keyboard ... which bears some resemblance to the bindings in programming that were discussed in this article.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;since v5.38 some object-oriented features are also &lt;a href="https://metacpan.org/dist/perl/view/pod/perlclass.pod" rel="noopener noreferrer"&gt;implemented in Perl core&lt;/a&gt;; but CPAN object-oriented frameworks like &lt;code&gt;Moose&lt;/code&gt; are still heavily used. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;See &lt;a href="https://metacpan.org/dist/perl/view/pod/perlsyn.pod#Declarations" rel="noopener noreferrer"&gt;perlsyn&lt;/a&gt;: "Declaring a subroutine allows a subroutine name to be used as if it were a list operator from that point forward in the program". ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;the notation &lt;code&gt;=&amp;gt;&lt;/code&gt; is also present in JavaScript, but with a meaning totally different from Perl: it is used for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" rel="noopener noreferrer"&gt;arrow function expressions&lt;/a&gt;, a compact alternative to traditional function expression. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl feature: trailing commas</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Sun, 22 Feb 2026 22:14:50 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-trailing-commas-4504</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-trailing-commas-4504</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;The last two posts about &lt;a href="https://dev.to/damil/beautiful-perl-feature-blocks-2o4"&gt;lexical scoping&lt;/a&gt; and &lt;a href="https://dev.to/damil/beautiful-perl-feature-local-for-temporary-changes-to-global-variables-4ejk"&gt;dynamic scoping&lt;/a&gt; addressed deep subjects and therefore were very long; for this time, we'll discuss &lt;strong&gt;trailing commas&lt;/strong&gt;, a much lighter subject ... that nevertheless deserves detailed comments!&lt;/p&gt;
&lt;h2&gt;
  
  
  Trailing commas, basic principle
&lt;/h2&gt;

&lt;p&gt;Programming languages that support trailing commas are able to parse a list like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(1, 2, 3, 5, 8,)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without generating an error. In other words, it is legal to put a comma after the last item in the list; that comma is a no-op, so the list above is equivalent to &lt;code&gt;(1, 2, 3, 5, 8)&lt;/code&gt;. Of course the trailing comma is optional, not mandatory.&lt;/p&gt;

&lt;p&gt;When it appears on a single line, like in that example, the trailing comma seems ridiculous; but the interest is when the list is written on several lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apples&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
              &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;oranges&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
              &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bananas&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;Here the trailing comma facilitates &lt;em&gt;later changes to the code&lt;/em&gt;, should these become necessary. In this example if we want to comment out bananas, or to switch the order of the fruits, we can operate on single lines without having to care about which fruit comes last.&lt;/p&gt;

&lt;p&gt;This feature is a transposition of a principle already familiar in all languages with blocks, namely the fact that the last statement in a block can indifferently have a semicolon or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$is_simple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;do_simple_stuff&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="c1"&gt;# no semicolon&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                 &lt;span class="nv"&gt;process&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                 &lt;span class="nv"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;# with semicolon&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other arguments are commonly invoked in favor of trailing commas, like the facts that diffs in version control systems are cleaner, or that it is easier to generate code programmatically. Going into such arguments would take too much space here, but discussions on the matter can easily be found on the Internet.&lt;/p&gt;

&lt;p&gt;On the other hand, let us mention that some people object to trailing commas, arguing that enumeration sentences in natural language never end with a comma, but rather with a full stop or another punctuation sign that marks the end of the list. Evidently this is true, but a sentence in natural language, once emitted, is not rewritten, while in programming languages rewriting is quite frequent - for this usage trailing commas are interesting in programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  History and comparison with other languages
&lt;/h2&gt;

&lt;p&gt;Long ago the venerable ANSI C language already accepted trailing commas in array initializers; the same thing for enums was added in &lt;a href="https://en.wikipedia.org/wiki/C99" rel="noopener noreferrer"&gt;C99&lt;/a&gt;. Both features propagated into languages of C heritage, like C++, Java, PHP, etc., and of course Perl. But Perl went further: since the beginning (version 1.0 in 1987), Perl supported trailing commas in &lt;em&gt;all kinds of lists&lt;/em&gt;, including parameters to subroutines, assignments to lists of variables, or more recently in subroutine signatures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;@others&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@ARGV&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;draw_diagram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;Perl&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1987&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s"&gt;Python&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1991&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s"&gt;Java&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1995&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;transfer_content&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; 
                     &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;destination&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
                     &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;) {&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I strongly suspect that this early design decision in Perl had an influence on the later conception of other programming languages, although I couldn't find any evidence to prove it - influences are rarely documented in design documents! Here is a historical picture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; had trailing commas since the beginning (1991), but with some peculiarities that will be discussed below;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt; accepted trailing commas since the beginning (1995), but only in array initializers and enums, like in C; a &lt;a href="https://bugs.openjdk.org/browse/JDK-6407472" rel="noopener noreferrer"&gt;request to extend this to other lists&lt;/a&gt; was formulated in 2006 but was ignored;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript&lt;/strong&gt; accepted trailing commas in array literals since the beginning (1995); later support for allowing them in object literals was added in &lt;a href="https://www.w3schools.com/js/js_es5.asp?#mark_trailing_commas" rel="noopener noreferrer"&gt;ES5&lt;/a&gt; (2009) and also for function definitions and calls in &lt;a href="https://www.w3schools.com/js/js_2017.asp?#mark_trailing_commas" rel="noopener noreferrer"&gt;JS 2017&lt;/a&gt;. The global picture is well documented in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas" rel="noopener noreferrer"&gt;MDN documentation&lt;/a&gt;, and lots of examples are shown in a &lt;a href="https://blog.logrocket.com/best-practices-using-trailing-commas-javascript/" rel="noopener noreferrer"&gt;blog by logrocket&lt;/a&gt;. However JavaScript has a strange edge case with array literals, which will be discussed below. Furthermore, beware that &lt;strong&gt;JSON&lt;/strong&gt;, not a programming language but a data interchange format closely related to JavaScript, does &lt;strong&gt;not&lt;/strong&gt; support trailing commas;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C++&lt;/strong&gt; inherited from C a restricted use of trailing commas; a &lt;a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3776r1.html" rel="noopener noreferrer"&gt;recent proposal (2025)&lt;/a&gt; to extend the support to more general use cases is still pending;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin&lt;/strong&gt; added general support for trailing commas in &lt;a href="https://kotlinlang.org/docs/whatsnew14.html#trailing-comma" rel="noopener noreferrer"&gt;version 1.4.0 (2020)&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP&lt;/strong&gt; extended its support for trailing commas in &lt;a href="https://php.watch/versions/8.0/trailing-comma-parameter-use-list" rel="noopener noreferrer"&gt;version 8.0 (2020)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So nowadays there seems to be a clear tendency towards adoption of trailing commas in many major languages, and some languages are still working on extending their support in this area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge cases in other languages
&lt;/h2&gt;

&lt;p&gt;Trailing commas in Perl are &lt;strong&gt;true no-ops&lt;/strong&gt;, in &lt;strong&gt;every context&lt;/strong&gt;. Furthermore, intermediate commas in a list, or several commas at the end, are also allowed, without any semantic consequence; this is not very useful, but has the nice property of requiring &lt;em&gt;absolutely no reasoning from the programmer&lt;/em&gt;, for example when large chunks of code are reshuffled in the course of a refactoring operation. By contrast, Python and JavaScript have edge cases, as shown in the rest of this chapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python : the tuple exception
&lt;/h3&gt;

&lt;p&gt;In Python the array expression &lt;code&gt;[1, 2, 3,]&lt;/code&gt; is legal, but expressions &lt;code&gt;[1, 2, , 3,]&lt;/code&gt; or &lt;code&gt;[1, 2, 3,,]&lt;/code&gt; are not: in other words, intermediate commas or multiple trailing commas are not allowed. This is just a minor syntactic restriction, not very annoying. &lt;/p&gt;

&lt;p&gt;A more severe peculiarity is the "tuple exception", namely the fact that these two expressions are &lt;em&gt;semantically different&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# single value
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;   &lt;span class="c1"&gt;# tuple with one member
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually, the syntax with the trailing comma is the &lt;em&gt;only way&lt;/em&gt; to write a singleton tuple. Another situation, related to the first, comes from the fact that tuples in some contexts are written without parenthesis; so these two lines are again semantically different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;  &lt;span class="c1"&gt;# assign a scalar value to x
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# assign a singleton tuple to x
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;whereas with tuples of more than one element, the trailing comma is a true no-op:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="c1"&gt;# assign a triple to x
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# same thing
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Furthermore, in singleton &lt;em&gt;lists&lt;/em&gt; (as opposed to singleton &lt;em&gt;tuples&lt;/em&gt;), trailing commas are also a no-op:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;      &lt;span class="c1"&gt;# assign a singleton list to y
&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,]&lt;/span&gt;     &lt;span class="c1"&gt;# same thing
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when trailing commas appear in Python code, some thought is required to get the proper meaning.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript: the sparse array exception
&lt;/h3&gt;

&lt;p&gt;Now let us consider trailing commas in JavaScript. Within &lt;em&gt;object literals&lt;/em&gt;, they are true no-ops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// equivalent to {x:1, y:2}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but like in Python, it is not possible to write intermediate commas or several trailing commas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Uncaught SyntaxError: Unexpected token ','&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,,&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;// idem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The situation with &lt;em&gt;array literals&lt;/em&gt; is quite different: there the syntax admits intermediate commas and several trailing commas, but semantically they &lt;em&gt;occupy slots in the array&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,,,]&lt;/span&gt; &lt;span class="c1"&gt;// [ 1, &amp;lt;1 empty item&amp;gt;, 2, 3, &amp;lt;2 empty items&amp;gt; ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is an array of length 6, but with only 3 occupied slots - something that is called a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#sparse_arrays" rel="noopener noreferrer"&gt;sparse array&lt;/a&gt; in JavaScript parlance. Empty slots in the array are not equivalent to &lt;code&gt;undefined&lt;/code&gt;; their meaning depends on the operation applied to the array, as explained in this &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#sparse_arrays" rel="noopener noreferrer"&gt;MDN document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like in Python, when trailing commas appear in JavaScript code, some thought is required to get the proper meaning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Trailing commas are a relatively minor topic, but it is interesting to observe that Perl since its initial design made wise decisions with this feature. Trailing commas are treated consistently in all Perl programming constructs, without any surprises for the programmer. In comparison to C, Perl widened the contexts where trailing commas were admitted, and this was probably an inspiration to many other programming languages. Isn't that beautiful ?&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;The cover picture shows the initial bars of fugue &lt;a href="https://fr.wikipedia.org/wiki/Pr%C3%A9lude_et_fugue_en_sol_mineur_(BWV_885)" rel="noopener noreferrer"&gt;BWV885&lt;/a&gt; from Johann Sebastian Bach, in a manuscript which is not from the hand of the composer but was transmitted to us by his son-in-law Johann Christoph Altnickol. The theme of that fugue is very recognizable as it repeats the same note &lt;em&gt;seven times&lt;/em&gt; before moving to something else - so it reminded me of repeated commas! But this is just a wink; in reality, the illustration is absolutely not relevant with respect to the main theme of this article, because the repetition of notes in the theme is by no means a no-op - on the contrary, it is a strong reinforcement. On a violin a similar effect could be obtained by performing a &lt;em&gt;crescendo&lt;/em&gt; on a long note; but on a harpsichord or an organ a note cannot be changed after the initial attack - so repetition is another device to convey the idea of reinforcement.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl feature: 'local', for temporary changes to global variables</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Sun, 15 Feb 2026 18:51:01 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-local-for-temporary-changes-to-global-variables-4ejk</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-local-for-temporary-changes-to-global-variables-4ejk</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-3of1"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/damil/beautiful-perl-feature-blocks-2o4"&gt;last post&lt;/a&gt; was about BLOCKs and &lt;em&gt;lexical scoping&lt;/em&gt;, a feature present in almost all programming languages. By contrast, today's topic is about another feature quite unique to Perl : &lt;em&gt;dynamic scoping&lt;/em&gt;, introduced through the '&lt;code&gt;local&lt;/code&gt;' keyword. As we shall see, lexical scoping and dynamic scoping address different needs, and Perl allows us to &lt;em&gt;choose&lt;/em&gt; the scoping strategy most appropriate to each situation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using &lt;code&gt;local&lt;/code&gt; : an appetizer
&lt;/h2&gt;

&lt;p&gt;Let us start with a very simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;current time here is &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt; &lt;span class="nb"&gt;localtime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$zone&lt;/span&gt; &lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Asia/Tokyo&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Africa/Nairobi&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Europe/Athens&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="nv"&gt;$ENV&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$zone&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in &lt;/span&gt;&lt;span class="si"&gt;$zone&lt;/span&gt;&lt;span class="s2"&gt;, time is &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt; &lt;span class="nb"&gt;localtime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;but here current time is still &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt; &lt;span class="nb"&gt;localtime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl's &lt;code&gt;localtime&lt;/code&gt; builtin function returns the time "in the current timezone". On Unix-like systems, the notion of "current timezone" can be controlled through the &lt;code&gt;TZ&lt;/code&gt; environment variable, so here the program &lt;em&gt;temporarily&lt;/em&gt; changes that variable to get the local time in various cities around the world. At the end of the program, we get back to the usual local time. Here is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current time here is Sun Feb  8 22:21:41 2026
in Asia/Tokyo, time is Mon Feb  9 06:21:41 2026
in Africa/Nairobi, time is Mon Feb  9 00:21:41 2026
in Europe/Athens, time is Sun Feb  8 23:21:41 2026
but here current time is still Sun Feb  8 22:21:41 2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gist of that example is that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we want to call some code not written by us (here: the &lt;code&gt;localtime&lt;/code&gt; builtin function);&lt;/li&gt;
&lt;li&gt;the API of that code does not offer any parameter or option to tune its behaviour according to our needs; instead, it relies on some information in the &lt;em&gt;global state&lt;/em&gt; of the running program (here: the local timezone);&lt;/li&gt;
&lt;li&gt;apart from getting our specific result, we don't want the global state to be durably altered, because this could lead to unwanted side-effects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use cases similar to this one are very common, not only in Perl but in every programming language. There is always some kind of implicit global state that controls how the program behaves internally and how it interacts with its operating system: for example environment variables, command-line arguments, open sockets, signal handlers, etc. Each language has its strategies for dealing with the global state, but often the solutions are multi-faceted and domain-specific. Perl shines because its &lt;code&gt;local&lt;/code&gt; mechanism covers a very wide range of situations in a consistent way and is extremely simple to activate.&lt;/p&gt;

&lt;p&gt;Before going into the details, let us address the bad reputation of dynamic scoping. This mechanism is often described as something that should be absolutely avoided because it implements a kind of action at distance, yielding unpredictable program behaviour. Yes, it is totally true, and therefore languages that only have dynamic scoping are not suited for programming-in-the-large. Yet in specific contexts, dynamic scoping is acceptable or even appropriate. The most notable examples are Unix shells and also Microsoft Powershell for Windows, that still today all rely on dynamic scoping, probably because it's easier to implement.&lt;/p&gt;

&lt;p&gt;Perl1 also used dynamic scoping in its initial design, presumably for the same reason of easiness of implementation, and also because it was heavily influenced by shell programming and was addressing the same needs. When later versions of Perl evolved into a general-purpose language, the additional mechanism of lexical scoping was introduced because it was indispensable for larger architectures. Nevertheless, dynamic scoping &lt;strong&gt;was not removed&lt;/strong&gt;, partly for historical reasons, but also because &lt;em&gt;action at distance is precisely what you want in some specific situations&lt;/em&gt;. The next chapters will show you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mechanics of &lt;code&gt;local&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In the last post we saw that a &lt;code&gt;my&lt;/code&gt; declaration declares a &lt;em&gt;new&lt;/em&gt; variable, possibly shadowing a previous variable of the same name. By contrast, a &lt;code&gt;local&lt;/code&gt; declaration is only possible on &lt;em&gt;a global variable that already exists&lt;/em&gt;; the effect of the declaration is to temporarily &lt;em&gt;push aside the current value&lt;/em&gt; of that global variable, leaving room for a new value. After that operation, any code anywhere in the program that accesses the global variable will see the new value ... until the effect of &lt;code&gt;local&lt;/code&gt; is reverted, namely when exiting the scope in which the &lt;code&gt;local&lt;/code&gt; declaration started.&lt;/p&gt;

&lt;p&gt;Here is a very simple example, again based on the &lt;code&gt;%ENV&lt;/code&gt; global hash. This hash is automatically populated with a copy of the shell environment when perl starts up. We'll suppose that the initial value of &lt;code&gt;$ENV{USERNAME}&lt;/code&gt;, as transmitted from the shell, is &lt;code&gt;Alex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;greet_user&lt;/span&gt; &lt;span class="p"&gt;($salute) {&lt;/span&gt;
  &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$salute&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;$ENV&lt;/span&gt;&lt;span class="s2"&gt;{USERNAME}&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;                 &lt;span class="c1"&gt;# Hello, Alex&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$ENV&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brigitte&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Hi&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;                  &lt;span class="c1"&gt;# Hi, Brigitte&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$ENV&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Charles&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
    &lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Good morning&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;      &lt;span class="c1"&gt;# Good morning, Charles&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Still there&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;         &lt;span class="c1"&gt;# Still there, Brigitte&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Good bye&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;              &lt;span class="c1"&gt;# Good bye, Alex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same thing would work with a global package variable:&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;our&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alex&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;             &lt;span class="c1"&gt;# "our" declares a global package variable&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;greet_user&lt;/span&gt; &lt;span class="p"&gt;($salute) {&lt;/span&gt;
  &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$salute&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Hello&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="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brigitte&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="nv"&gt;greet_user&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;Hi&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="nv"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but if the variable is not pre-declared, we get an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Global symbol "$username" requires explicit package name (did you forget to declare "my $username"?)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or if the variable is pre-declared as &lt;em&gt;lexical&lt;/em&gt; through &lt;code&gt;my $username&lt;/code&gt; instead of &lt;code&gt;our $username&lt;/code&gt;, we get another error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can't localize lexical variable $username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the &lt;code&gt;local&lt;/code&gt; mechanism only applies to global variables. There are three categories of such variables:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;standard variables of the Perl interpreter;&lt;/li&gt;
&lt;li&gt;package members (of modules imported from CPAN, or of your own modules). This includes the whole symbol tables of those packages, i.e. not only the global variables, but also the subroutines or methods;&lt;/li&gt;
&lt;li&gt;what the Perl documentation calls &lt;a href="https://metacpan.org/pod/perlsub#Localization-of-elements-of-composite-types" rel="noopener noreferrer"&gt;elements of composite types&lt;/a&gt;, i.e. individual members of arrays or hashes. Such elements can be localized &lt;em&gt;even if the array or hash is itself a lexical variable&lt;/em&gt;, because while the entry point to the array or hash may be on the execution stack, its member elements are always stored in global heap memory. This last category of global variables is perhaps more difficult to understand, but we will give examples later to make it clear.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As we can see, the single and simple mechanism of dynamic scoping covers a vast range of applications! Let us explore the various use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Localizing standard Perl variables
&lt;/h2&gt;

&lt;p&gt;The Perl interpreter has a number of builtin special variables, listed in &lt;a href="https://metacpan.org/dist/perl/view/pod/perlvar.pod#SPECIAL-VARIABLES" rel="noopener noreferrer"&gt;perlvar&lt;/a&gt;. Some of them control the internal behaviour of the interpreter; some other are interfaces to the operating system (environment variables, signal handlers, etc.). These variables have reasonable default values that satisfy most common needs, but they can be changed whenever needed. If the change is for the whole program, a regular assignment instruction is good enough; but if it is for a temporary change in a specific context, &lt;code&gt;local&lt;/code&gt;is the perfect tool for the job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal variables of the interpreter
&lt;/h3&gt;

&lt;p&gt;The examples below are typical of idiomatic Perl programming: altering global variables so that builtin functions behave differently from the default.&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;# input record separator ($/)&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@lines&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;STDIN&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                     &lt;span class="c1"&gt;# regular mode, separating by newlines&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@paragraphs&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;do&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;STDIN&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;# paragraph mode, separating by 2 or more newlines&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$whole_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;do&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="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bp"&gt;STDIN&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;      &lt;span class="c1"&gt;# slurp mode, no separation&lt;/span&gt;

&lt;span class="c1"&gt;# output field and output record separators&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;write_csv_file&lt;/span&gt; &lt;span class="p"&gt;($rows, $filename) {&lt;/span&gt;
  &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;:unix&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cannot write into &lt;/span&gt;&lt;span class="si"&gt;$filename&lt;/span&gt;&lt;span class="s2"&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="s2"&gt;,&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;               &lt;span class="c1"&gt;# output field separator -- inserted between columns&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="se"&gt;\r\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;            &lt;span class="c1"&gt;# output row separator   -- inserted between rows&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nv"&gt;$fh&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="nv"&gt;@$rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# assuming that each member of @$rows is an arrayref&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# list separator in interpolated strings&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@perl_files&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*.&lt;/span&gt;&lt;span class="nv"&gt;pl&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# globbing perl files in the current directory&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@python_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;*.&lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# idem for python files&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="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;         &lt;span class="c1"&gt;# lists will be comma-separated when interpolated in a string&lt;/span&gt;
  &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I found these perl files: &lt;/span&gt;&lt;span class="si"&gt;@perl_files&lt;/span&gt;&lt;span class="s2"&gt; and these python files: &lt;/span&gt;&lt;span class="si"&gt;@python_files&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Interface to the operating system
&lt;/h3&gt;

&lt;p&gt;We have already seen two examples involving the &lt;code&gt;%ENV&lt;/code&gt; hash of environment variables inherited from the operating system. Likewise, it is possible to tweak the &lt;code&gt;@ARGV&lt;/code&gt; array before parsing the command-line arguments. Another interesting variable is the &lt;code&gt;%SIG&lt;/code&gt; hash of signal handlers, as documented in &lt;a href="https://metacpan.org/pod/perlipc#Handling-the-SIGHUP-Signal-in-Daemons" rel="noopener noreferrer"&gt;perlipc&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="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$SIG&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;HUP&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IGNORE&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt; &lt;span class="c1"&gt;# don't want to be disturbed for a while&lt;/span&gt;
  &lt;span class="nv"&gt;do_some_tricky_computation&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;Predefined handles like STDIN, STDOUT and STDERR can also be localized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;printing to regular STDOUT&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="nv"&gt;*STDOUT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="bp"&gt;STDOUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;captured_stdout.txt&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="vg"&gt;$!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;do_some_verbose_computation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;back to regular STDOUT&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Localizing package members
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Package global variables
&lt;/h3&gt;

&lt;p&gt;Global variables are declared with the &lt;code&gt;our&lt;/code&gt; keyword. The difference with lexical variables (declared with &lt;code&gt;my&lt;/code&gt;) is that such global variables are accessible, not only from within the package, but also from the outside, if prefixed by the package name. So if package &lt;code&gt;Foo::Bar&lt;/code&gt; declares &lt;code&gt;our ($x, @a, %h)&lt;/code&gt;, these variables are accessible from anywhere in the Perl program under &lt;code&gt;$Foo::Bar::x&lt;/code&gt;, &lt;code&gt;@Foo::Bar::a&lt;/code&gt; or &lt;code&gt;%Foo::Bar::h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Many CPAN modules use such global variables to expose their public API. For example, the venerable &lt;a href="https://metacpan.org/pod/Data::Dumper" rel="noopener noreferrer"&gt;Data::Dumper&lt;/a&gt; chooses among various styles for dumping a data structure, depending on the &lt;code&gt;$Data::Dumper::Indent&lt;/code&gt; variable. The default (style 2) is optimized for readability, but sometimes the compact style 0 is more appropriate:&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;print&lt;/span&gt; &lt;span class="nv"&gt;Dumper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data_tree&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;Data::Dumper::&lt;/span&gt;&lt;span class="nv"&gt;Indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;Dumper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$other_tree&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://metacpan.org/pod/Carp" rel="noopener noreferrer"&gt;Carp&lt;/a&gt; or &lt;a href="https://metacpan.org/pod/URI" rel="noopener noreferrer"&gt;URI&lt;/a&gt; are other examples of well-known modules where global variables are used as a configuration API.&lt;/p&gt;

&lt;p&gt;Modules with this kind of architecture are often pretty old; more recent modules tend to prefer an object-oriented style, where the configuration options are given as options to the &lt;code&gt;new()&lt;/code&gt; method instead of using global variables. Of course the object-oriented architecture offers better encapsulation, since a large program can work with several instances of the same module, each instance having its own configuration options, without interference between them. This is not to say, however, that object-oriented configuration is &lt;em&gt;always&lt;/em&gt; the best solution: when it comes to tracing, debugging or profiling needs, it is often very convenient to be able to tune a global knob and have its effect applied to the whole program: in those situations, what you want is just the opposite of strict encapsulation! Therefore some modules, although written in a modern style, still made the wise choice of leaving some options expressed as global variables; changing these options has a global effect, but thanks to &lt;code&gt;local&lt;/code&gt; this effect can be limited to a specific scope. Examples can be found in &lt;a href="https://metacpan.org/pod/Type::Tiny#Package-Variables" rel="noopener noreferrer"&gt;Type::Tiny&lt;/a&gt; or in &lt;a href="https://metacpan.org/pod/List::Util#CONFIGURATION-VARIABLES" rel="noopener noreferrer"&gt;List::Util&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subroutines (aka monkey-patching)
&lt;/h3&gt;

&lt;p&gt;Every package has a &lt;em&gt;symbol table&lt;/em&gt; that contains not only its global variables, but also the subroutines (or methods) declared in that package. Since the symbol table is writeable, it is possible to overwrite any subroutine, thereby changing the behaviour of the package - an operation called &lt;a href="https://en.wikipedia.org/wiki/Monkey_patch" rel="noopener noreferrer"&gt;monkey-patching&lt;/a&gt;. Of course monkey-patching could easily create chaos, so it should be used with care - but in some circumstances it is extremely powerful and practical. In particular, testing frameworks often use monkey-patching for mocking interactions with the outside world, so that the internal behaviour of a sofware component can be tested in isolation.&lt;/p&gt;

&lt;p&gt;The following example is not very realistic, but it's the best I could come up with to convey the idea in just a few lines of code. Consider a big application equipped with a &lt;em&gt;logger&lt;/em&gt; object. Here we will use a logger from &lt;a href=""&gt;Log::Dispatch&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Log::&lt;/span&gt;&lt;span class="nv"&gt;Dispatch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Log::&lt;/span&gt;&lt;span class="nv"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;outputs&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[['&lt;/span&gt;&lt;span class="s1"&gt;Screen&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;min_level&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="s"&gt;newline&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logger has methods &lt;code&gt;debug()&lt;/code&gt;, &lt;code&gt;info()&lt;/code&gt;, &lt;code&gt;error()&lt;/code&gt;, etc. for accepting messages at different levels. Here it is configured to only log messages starting from level &lt;code&gt;info&lt;/code&gt;; so when the client code calls &lt;code&gt;info()&lt;/code&gt;, the message is printed, while calls to &lt;code&gt;debug()&lt;/code&gt; are ignored. As a result, when the following routine is called, we normally only see the messages "start working ..." and "end working ...":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;work&lt;/span&gt; &lt;span class="p"&gt;($phase) {&lt;/span&gt;
  &lt;span class="nv"&gt;$log&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;info&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;start working on &lt;/span&gt;&lt;span class="si"&gt;$phase&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
  &lt;span class="nv"&gt;$log&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;weird condition while doing &lt;/span&gt;&lt;span class="si"&gt;$phase&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt; &lt;span class="c1"&gt;# normally not seen - level below 'info'&lt;/span&gt;
  &lt;span class="nv"&gt;$log&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;info&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;end working on &lt;/span&gt;&lt;span class="si"&gt;$phase&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now suppose that we don't want to change the log level for the whole application, but nevertheless we need to see the debug messages at a given point of execution. One (dirty!) way of achieving this is to temporarily treat calls to &lt;code&gt;debug()&lt;/code&gt; as if they were calls to &lt;code&gt;info()&lt;/code&gt;. So a scenario 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="nv"&gt;work&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;initial setup&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="nv"&gt;*&lt;/span&gt;&lt;span class="nn"&gt;Log::Dispatch::&lt;/span&gt;&lt;span class="nv"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;*&lt;/span&gt;&lt;span class="nn"&gt;Log::Dispatch::&lt;/span&gt;&lt;span class="nv"&gt;info&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# temporarily alias the 'debug' method to 'info'&lt;/span&gt;
  &lt;span class="nv"&gt;work&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;core stuff&lt;/span&gt;&lt;span class="p"&gt;")}&lt;/span&gt;
&lt;span class="nv"&gt;work&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;logs the following sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;start working on initial setup
end working on initial setup

start working on core stuff
weird condition while doing core stuff
end working on core stuff

start working on cleanup
end working on cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monkey-patching techniques are not specific to Perl; they are used in all dynamic languages (Python, Javascript, etc.), not for regular programming needs, but rather for testing or profiling tasks. However, since other dynamic languages do not have the &lt;code&gt;local&lt;/code&gt; mechanism, temporary changes to the symbol table must be programmed by hand, by storing the initial code reference in a temporary variable, and restoring it when exiting from the monkey-patched scope. This is a bit more work and is more error-prone. Often there are library modules for making the job easier, though: see for example &lt;a href="https://docs.pytest.org/en/7.1.x/how-to/monkeypatch.html" rel="noopener noreferrer"&gt;https://docs.pytest.org/en/7.1.x/how-to/monkeypatch.html&lt;/a&gt; in Python.&lt;/p&gt;

&lt;p&gt;Monkey-patching in a statically-typed language like Java is more acrobatic, as shown in &lt;a href="https://blog.frankel.ch/monkeypatching-java/" rel="noopener noreferrer"&gt;Nicolas Fränkel's blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Localizing elements of arrays or hashes
&lt;/h2&gt;

&lt;p&gt;The value of an array at a specific index, or the value of a hash for a specific key, can be localized too. We have already seen some examples with the builtin hashes &lt;code&gt;%ENV&lt;/code&gt; or &lt;code&gt;%SIG&lt;/code&gt;, but it works as well on user data, even when the data structure is several levels deep. A typical use case for this is when a Web application loads a JSON, YAML or XML config file at startup. The config data becomes a nested tree in memory; if for any reason that config data must be changed at some point, &lt;code&gt;local&lt;/code&gt; can override a specific data leaf, or any intermediate subtree, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;logger_file&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/opt/log/special.log&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/opt/data/app_session&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;
                                     &lt;span class="s"&gt;expires&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42900&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;Another example can be seen in my &lt;a href="https://metacpan.org/pod/Data::Domain" rel="noopener noreferrer"&gt;Data::Domain&lt;/a&gt; module. The job of that module is to walk through a datatree and check if it meets the conditions expected by a "domain". The &lt;code&gt;inspect()&lt;/code&gt; method that does the checking sometimes needs to know at which node it is currently located; so a &lt;code&gt;$context&lt;/code&gt; tree is worked upon during the traversal and passed to every method call. With the help of &lt;code&gt;local&lt;/code&gt;, temporary changes to the shape of &lt;code&gt;$context&lt;/code&gt; are very easy to implement:&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="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n_items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An alternative could have been to just push &lt;code&gt;$i&lt;/code&gt; on top of the &lt;code&gt;@{$context-&amp;gt;{path}}&lt;/code&gt; array, and then pop it back at the end of the block. But since this code may call subclasses written by other people, with little guarantee on how they would behave with respect to &lt;code&gt;$context-&amp;gt;{path}&lt;/code&gt;, it is safer to localize it and be sure that &lt;code&gt;$context-&amp;gt;{path}&lt;/code&gt; is in a clean state when starting the next iteration of the loop. Interested readers can skim through the &lt;a href="https://metacpan.org/dist/Data-Domain/source/lib/Data/Domain.pm" rel="noopener noreferrer"&gt;source code&lt;/a&gt; to see the full story. A similar technique can also be observed in &lt;a href="https://metacpan.org/dist/Catalyst-Runtime/source/lib/Catalyst/Dispatcher.pm#L212" rel="noopener noreferrer"&gt;Catalyst::Dispatcher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A final example is the well-known &lt;a href="https://metacpan.org/pod/DBI" rel="noopener noreferrer"&gt;DBI&lt;/a&gt; module, whose rich API exploits several Perl mechanisms simultaneously. DBI is principally object-oriented, except that the objects are called "handles"; but in addition to methods, handles also have "attributes" accessible as hash members. The DBI documentation explicitly recommends to use &lt;code&gt;local&lt;/code&gt; for temporary modifications to the values of attributes, for example for the &lt;a href="https://metacpan.org/pod/DBI#RaiseError" rel="noopener noreferrer"&gt;RaiseError&lt;/a&gt; attribute. This is interesting because it shows a dichotomy between API styles: if DBI had a purely object-oriented style, with usual &lt;a href="https://metacpan.org/dist/perl/view/pod/perlootut.pod#Attributes" rel="noopener noreferrer"&gt;getter and setter methods&lt;/a&gt;, it would be impossible to use the benefits of &lt;code&gt;local&lt;/code&gt; - temporary changes to an attribute followed by a revert to the previous value would have to be programmed by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  How other languages handle temporary changes to global state
&lt;/h2&gt;

&lt;p&gt;As argued earlier, the need for temporary changes to global state occurs in every programming language, in particular for testing, tracing or profiling tasks. When dynamic scoping is not present, the most common solution is to write specific code for storing the old state in a temporary variable, implement the change for the duration of a given computation, and then restore the old state. A common best practice for such situations is to use a &lt;code&gt;try ... finally ...&lt;/code&gt; construct, where restoration to the old state is implemented in the &lt;code&gt;finally&lt;/code&gt; clause: this guarantees that even if exceptions occur, the code exits with a clean state. Most languages do possess such constructs - this is definitely the case for Java, JavaScript and Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python context managers
&lt;/h3&gt;

&lt;p&gt;Python has a mechanism more specifically targeted at temporary changes of context : this is called &lt;a href="https://docs.python.org/3/reference/datamodel.html#context-managers" rel="noopener noreferrer"&gt;context manager&lt;/a&gt;, triggered through a &lt;a href="https://docs.python.org/3/reference/compound_stmts.html#with" rel="noopener noreferrer"&gt;with statement&lt;/a&gt;. A context manager implements special methods &lt;code&gt;__enter__()&lt;/code&gt; and &lt;code&gt;__exit__()&lt;/code&gt; that can be programmed to operate changes into the global context. This technique offers more precision than Perl's &lt;code&gt;local&lt;/code&gt; construct, since the enter and exit methods are free to implement any kind of computation; however it is less general, because each context manager is specialized for a specific task. Python's &lt;a href="https://docs.python.org/3/library/contextlib.html" rel="noopener noreferrer"&gt;contextlib&lt;/a&gt; library provides a collection of context managers for common needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Perl's &lt;code&gt;local&lt;/code&gt; mechanism is often misunderstood. It is frowned upon because it breaks encapsulation - and this criticism is perfectly legitimate as far as regular programming tasks are concerned; but on the other hand, it is a powerful and clean mechanism for &lt;em&gt;temporary changes to the global execution state&lt;/em&gt;. It solves real problems with surprising grace, and it’s one of the features that makes Perl uniquely expressive among modern languages. So do not follow the common advice to avoid &lt;code&gt;local&lt;/code&gt; at all costs, but learn to identify the situations where &lt;code&gt;local&lt;/code&gt; will be a helpful tool to you!&lt;/p&gt;

&lt;p&gt;Beyond the mere mechanism, the question is more at the level of philosophy of programming: to which extent should we enforce strict encapsulation of components? In an ideal world, each component has a well-defined interface, and interactions are only allowed to go through the official interfaces. But in a big assembly of components, we may encounter situations that were not foreseen by the designers of the individual components, and require inserting some additional screws, or drilling some additional holes, so that the global assembly works satisfactorily. This is where Perl's &lt;code&gt;local&lt;/code&gt; is a beautiful device.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover picture
&lt;/h2&gt;

&lt;p&gt;The cover picture&lt;sup id="fnref1"&gt;1&lt;/sup&gt; represents a violin with a modified global state: the two intermediate strings are crossed! This is the most spectacular example of &lt;a href="https://en.wikipedia.org/wiki/Scordatura" rel="noopener noreferrer"&gt;scordatura&lt;/a&gt; in Heirich Biber's &lt;a href="https://en.wikipedia.org/wiki/Rosary_Sonatas" rel="noopener noreferrer"&gt;Rosary sonatas&lt;/a&gt; (sometimes also called "Mystery sonatas"). Each sonata in the collection requires to tune the violin in a specific way, different from the standard tuning in fifths, resulting in very different atmospheres. It requires some intellectual gymnastics from the player, because the notes written in the score no longer represent the actual sounds heard, but merely refer to the locations of fingers on a normal violin; in other words, this operation is like monkey-patching a violin!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;small&gt;&lt;a href="http://creativecommons.org/licenses/by-sa/3.0/" rel="noopener noreferrer"&gt;CC BY-SA 3.0&lt;/a&gt;, &lt;a href="https://commons.wikimedia.org/w/index.php?curid=110521795" rel="noopener noreferrer"&gt;https://commons.wikimedia.org/w/index.php?curid=110521795&lt;/a&gt;&lt;/small&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl feature: BLOCKs</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Sat, 07 Feb 2026 19:54:28 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-feature-blocks-2o4</link>
      <guid>https://dev.to/damil/beautiful-perl-feature-blocks-2o4</guid>
      <description>&lt;h2&gt;
  
  
  Beautiful Perl series
&lt;/h2&gt;

&lt;p&gt;This post is part of the &lt;em&gt;beautiful Perl features&lt;/em&gt; series.&lt;br&gt;
See the &lt;a href="https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-b6a"&gt;introduction post&lt;/a&gt; for general explanations about the series.&lt;/p&gt;
&lt;h2&gt;
  
  
  BLOCK : sequence of statements
&lt;/h2&gt;

&lt;p&gt;Today's topic is the construct named BLOCK in the &lt;a href="https://metacpan.org/pod/perlsyn#Compound-Statements" rel="noopener noreferrer"&gt;perl documentation&lt;/a&gt;: a sequence of statements enclosed in curly brackets &lt;code&gt;{}&lt;/code&gt;. Both the concept and the syntax are common to many programming languages - they can also be found in languages of C heritage like Java, JavaScript and C++, among others; but Perl is different on various aspects - read on to dig into the details.&lt;/p&gt;

&lt;p&gt;BLOCKs in Perl may be used:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;as part of a compound statement, after an initial control flow construct like &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;foreach&lt;/code&gt;, etc.;&lt;/li&gt;
&lt;li&gt;as the body of a &lt;code&gt;sub&lt;/code&gt; declaration (subroutine or function);&lt;/li&gt;
&lt;li&gt;at any location where a single statement is expected. Obviously it would also be possible to just insert a plain sequence of statements, but enclosing them in a BLOCK has the advantage of creating a new delimited &lt;em&gt;lexical scope&lt;/em&gt; so that the effect of inner declarations is guaranteed to end when control flow exits the BLOCK. Details about lexical scopes are discussed below;&lt;/li&gt;
&lt;li&gt;as part of a &lt;code&gt;do&lt;/code&gt; expression, so that the whole BLOCK becomes a value that can be inserted within a more complex expression. This may be convenient for clarity of thought in some algorithms, and also for avoiding a subroutine call when efficiency is at stake.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All modern programmming languages have constructs equivalent to usages 1 and 2, because these are crucial for structuring algorithms and for handling complexity in programming. Usage 3 is less common, and usage 4 is quite particular to Perl. The next chapters will cover these various aspects in more depth.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lexical scope
&lt;/h2&gt;

&lt;p&gt;In all usage situations listed above, a Perl BLOCK always opens a new &lt;em&gt;lexical scope&lt;/em&gt;, i.e. a portion of code that delimits the effect of inner &lt;em&gt;declarations&lt;/em&gt;. Things that can be temporarily declared inside a lexical scope are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;lexical variables&lt;/strong&gt;, temporarily binding a variable name to a memory location on the stack - declared through keywords &lt;code&gt;my&lt;/code&gt; or &lt;code&gt;state&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lexical pragmata&lt;/strong&gt;, temporarily importing semantics into the current BLOCK - introduced through keywords &lt;code&gt;use&lt;/code&gt; or  &lt;code&gt;no&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;(beginning with Perl 5.18) &lt;strong&gt;lexical subroutines&lt;/strong&gt;, only accessible within the scope - also declared through keywords &lt;code&gt;my&lt;/code&gt; or &lt;code&gt;state&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://commons.wikimedia.org/wiki/File:Floral_matryoshka_set_2_smallest_doll_nested.JPG" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F4%2F41%2FFloral_matryoshka_set_2_smallest_doll_nested.JPG%2F512px-Floral_matryoshka_set_2_smallest_doll_nested.JPG%3F20080325170048" title="Embedded matryoshka dolls, credit © BrokenSphere / Wikimedia Commons" alt="The smallest doll in a set of matryoshkas" width="512" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a BLOCK is used as part of a compound statement (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;foreach&lt;/code&gt;, etc.), the initial clause before the BLOCK is already part of the lexical scope, so that variables declared in that clause can then be used within the BLOCK:&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;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$member&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;work_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$member&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;# here $member can be used&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$member&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;# ERROR : $member is no longer in scope&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also true when a compound statement has &lt;em&gt;several clauses&lt;/em&gt; and therefore several BLOCKs, like &lt;code&gt;if (...) {...} elsif {...} else {...}&lt;/code&gt;. Further examples, together with detailed explanations, can be found in &lt;a href="https://metacpan.org/pod/perlsub#Private-Variables-via-my()" rel="noopener noreferrer"&gt;perlsub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Declarations of variables, pragmata or subroutines have the following facts in common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they take effect starting from the statement &lt;em&gt;after&lt;/em&gt; the declaration. Technically declarations can occur anywhere in the BLOCK; the most common usage is to put them at the beginning, but there is no obligation to do so;&lt;/li&gt;
&lt;li&gt;they may temporarily &lt;em&gt;shadow&lt;/em&gt; the effect of declarations in higher scopes;&lt;/li&gt;
&lt;li&gt;their effect &lt;em&gt;ends when control flow exits the BLOCK&lt;/em&gt;, whatever the exit cause may be (normal end of the block, explicit exit through instructions like &lt;code&gt;return&lt;/code&gt;, &lt;code&gt;next&lt;/code&gt; or &lt;code&gt;goto&lt;/code&gt;, or exit because an exception was encountered).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Declarations in lexical scopes have effects both at &lt;strong&gt;compile-time&lt;/strong&gt; (the Perl interpreter temporarily alters its parsing rules) and at &lt;strong&gt;runtime&lt;/strong&gt; (the interpreter temporarily allocates or releases resources). For example in the following snippet:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$db_handle&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;DBI&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@db_connection_args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@large_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$db_handle&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;selectall_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$some_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;@some_bind_values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$file_handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;$output_file&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;could not open &lt;/span&gt;&lt;span class="si"&gt;$output_file&lt;/span&gt;&lt;span class="s2"&gt;: $!&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nv"&gt;$file_handle&lt;/span&gt; &lt;span class="nv"&gt;formatted_ouput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="nv"&gt;@large_array&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the interpreter knows at compile-time that variables &lt;code&gt;$db_handle&lt;/code&gt;, &lt;code&gt;@large_array&lt;/code&gt; and &lt;code&gt;$file_handle&lt;/code&gt; are allowed within the BLOCK, but not outside of it, so it can check statically for typos or other misuses of variables names; then at runtime the interpreter will dynamically allocate and release memory and external handles when control flow crosses the BLOCK. This is quite similar to what happens in a statically typed language like Java. By contrast, Python, often grouped in the same family as Perl because it is also a dynamically-typed language, does not have the same treatment of lexical scopes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lexical scopes in Python are not like Perl
&lt;/h3&gt;

&lt;p&gt;In Python, there is no generally available construct as versatile as a Perl BLOCK. Subsequences of statements are expressed through indentation, but this is only allowed as part of a function definition or as part of a &lt;a href="https://docs.python.org/3/reference/compound_stmts.html" rel="noopener noreferrer"&gt;compound statement&lt;/a&gt;. A compound statement must always start with a keyword (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, etc.) that opens the header clause and is followed by a &lt;em&gt;suite&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_success&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;summarize_results&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;report_to_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;cleanup_resources&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 'suite' in Python is not to be confused with a 'block'. The official documentation is very careful about the distinction, but many informal texts in Python literature make the confusion; yet the difference is quite important because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Python &lt;strong&gt;block&lt;/strong&gt;, "a piece of Python program text that is executed as a unit", only occurs within a module, a function body or a class definition (&lt;a href="https://docs.python.org/3/reference/executionmodel.html#structure-of-a-program" rel="noopener noreferrer"&gt;https://docs.python.org/3/reference/executionmodel.html#structure-of-a-program&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;a Python &lt;strong&gt;suite&lt;/strong&gt;, "a group of statements controlled by a clause", occurs whenever a clause in a compound statement expects to be followed by some instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blocks and suites look similar, because they are both expressed as indented sequences of statements; but the difference is that a 'block' opens a new lexical scope, while a 'suite' does not. In particular, this means that variables declared in a compound statement are still available after the statement has ended, which is quite surprising for programmers coming from a C-like culture (including Perl and Java). So for example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is valid Python code and prints 3. This example is taken from &lt;a href="https://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/" rel="noopener noreferrer"&gt;https://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/&lt;/a&gt; which does a very good job at explaining why Python in this respect works differently from many other languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lexical scope vs dynamic scope
&lt;/h3&gt;

&lt;p&gt;In addition to traditional lexical scoping, Perl also has another construct named &lt;em&gt;dynamic scoping&lt;/em&gt;, introduced through the keyword &lt;code&gt;local&lt;/code&gt;. Dynamic scoping is a vestige from Perl1, but still very useful in some specific use cases; it will be discussed in a future post in this series. For the moment let us just say that in all common situations, lexical scoping is the most appropriate mechanism for working with variables guaranteed not to interfere with the global state of the program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lexical variables
&lt;/h2&gt;

&lt;p&gt;Lexical variables in Perl are introduced with the &lt;code&gt;my&lt;/code&gt; keyword. Several variables, possibly of different types, can be declared and initialized in one single 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;my&lt;/span&gt; &lt;span class="nv"&gt;@table&lt;/span&gt;               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sx"&gt;qw/x y z/&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nb_rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nb_cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;scalar&lt;/span&gt; &lt;span class="nv"&gt;@table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@db_connection_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;%select_args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Variable initialization and list destructuring
&lt;/h3&gt;

&lt;p&gt;Lexical variables can only be used starting from the statement &lt;em&gt;after&lt;/em&gt; the declaration. Therefore it is illegal in Perl to write 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="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because at the point where expression &lt;code&gt;$x + 1&lt;/code&gt; is encountered, variable &lt;code&gt;$x&lt;/code&gt; is not yet in scope. By contrast, Java would accept &lt;code&gt;int x = 123, y = x + 1, z = x + 2&lt;/code&gt;, or JavaScript would accept &lt;code&gt;let x = 123, y = x + 1, z = x + 2&lt;/code&gt;, because in those languages variable initializations occur in sequence, while Perl starts by evaluating the complete list on the right-hand side of the assignment, and then distributes the values into variables on the left-hand side. &lt;/p&gt;

&lt;p&gt;Python is like Perl: it does not accept &lt;code&gt;x, y = 123, x + 1&lt;/code&gt; because &lt;code&gt;x&lt;/code&gt; is not defined in the right-hand side. Both Perl and Python had from the start the notion of "destructuring" a list into several individual variables. Other languages adopted similar features much later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript has an advanced mechanism of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring" rel="noopener noreferrer"&gt;destructuring&lt;/a&gt; since ES6 (2015), that can be applied not only to lists, but also to objects (records). For destructuring a list the syntax variables must be put in angle brackets on the left-hand side of the assignment, in order to avoid ambiguity with sequences of ordinary assignments:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// sequence of assignments&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;124&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;    &lt;span class="c1"&gt;// list destructuring&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://openjdk.org/projects/amber/" rel="noopener noreferrer"&gt;Amber project&lt;/a&gt; for Java recently introduced several mechanisms for &lt;em&gt;pattern matching&lt;/em&gt;, which is quite close to the idea of destructuring. However for the moment it can only be used for destructuring records, but not yet for lists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming back to Perl, list destructuring has always been part of common idioms, notably for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extracting items from command-line arguments
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;@others&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@ARGV&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;extracting items from the argument list to a subroutine
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$depth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;switching variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Shadowing variables from higher scopes
&lt;/h3&gt;

&lt;p&gt;Like in other languages, a lexical variable in Perl can &lt;em&gt;shadow&lt;/em&gt; another variable of the same name at a higher lexical scope. However, the shadowing effect only starts at the statement after the declaration of the variable. As a result, the shadowed value can still be used in the initializing expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;987&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inner scope, x is &lt;/span&gt;&lt;span class="si"&gt;$x&lt;/span&gt;&lt;span class="s2"&gt; and y is &lt;/span&gt;&lt;span class="si"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt; &lt;span class="c1"&gt;# "inner scope, x is 123 and y is 988"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;outer scope, x is &lt;/span&gt;&lt;span class="si"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;               &lt;span class="c1"&gt;# "outer scope, x is 987"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let us see how other dynamically typed languages handle variable shadowing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shadowing variables in Python
&lt;/h4&gt;

&lt;p&gt;Python has no explicit variable declarations; instead, any assignment instruction implicitly declares the target of the assignment to be a lexical variable in the current lexical scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="c1"&gt;# declares lexical variable x
&lt;/span&gt;    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt; &lt;span class="c1"&gt;# declares lexical variable y
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;789&lt;/span&gt; &lt;span class="c1"&gt;# assigns a new value to existing variable x
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the &lt;em&gt;intention&lt;/em&gt; of declaring is not explicitly stated by the programmer, the interpreter is of little help for detecting errors that would be identified as typos in other languages. In the example above, one could suspect that the intent was to declare a &lt;code&gt;z&lt;/code&gt; variable instead of assigning a new value to &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If an assignment occurs in the middle of a lexical scope, the corresponding variable is nevertheless treated as being lexical &lt;em&gt;from the very beginning of the scope&lt;/em&gt;. As a consequence, newcomers to Python can easily be surprised by an &lt;a href="https://docs.python.org/3/faq/programming.html#faq-unboundlocalerror" rel="noopener noreferrer"&gt;UnboundLocalError&lt;/a&gt;, which can be shortly demonstrated by this example from the official documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the assignment &lt;code&gt;x += 1&lt;/code&gt; implicitly declares &lt;code&gt;x&lt;/code&gt; to be a lexical variable &lt;em&gt;for the whole body&lt;/em&gt; of the &lt;code&gt;foo()&lt;/code&gt; function, even if the assignment comes at the end. In this situation the &lt;code&gt;print()&lt;/code&gt; statement raises an exception because at this point lexical variable &lt;code&gt;x&lt;/code&gt; is not bound to a value. By contrast, if the assignment is commented out&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# x += 1
&lt;/span&gt;
&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the program happily prints 10, because here &lt;code&gt;x&lt;/code&gt; is no longer interpreted as a lexical variable, but as the global &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Python statements &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#the-global-statement" rel="noopener noreferrer"&gt;global&lt;/a&gt; and &lt;a href="https://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement" rel="noopener noreferrer"&gt;nonlocal&lt;/a&gt; can instruct the parser that some specific variables should &lt;strong&gt;not&lt;/strong&gt; be declared in the current lexical scope, but should instead be taken from the global module scope, or, in case of nested functions or classes, from the next higher scope. So on this respect, Python programming is just the opposite to Perl or Java : instead of explicitly declaring lexical variables, one must explicitly declare the variables that are &lt;strong&gt;not&lt;/strong&gt; lexical. Furthermore, since such declarations apply to the whole current lexical scope, independently of the place where they are inserted, it is an exclusive choice : any use of a named variable must be either from the current lexical scope or from a higher scope or from the global scope. Therefore it is not possible, like in Perl, to use the value of global &lt;code&gt;x&lt;/code&gt; in the initialization expression for local lexical &lt;code&gt;x&lt;/code&gt;. &lt;/p&gt;

&lt;h4&gt;
  
  
  Shadowing variables in JavaScript
&lt;/h4&gt;

&lt;p&gt;The historical construct for declaring lexical variables in JavaScript was through the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var" rel="noopener noreferrer"&gt;&lt;code&gt;var&lt;/code&gt;&lt;/a&gt; keyword, which is still present in the language. The behaviour of &lt;code&gt;var&lt;/code&gt; is quite similar to Python lexical variables: variables appear to exist even before they are declared (which is called &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Hoisting" rel="noopener noreferrer"&gt;hoisting&lt;/a&gt; in JavaScript); they are scoped by functions or modules, not by blocks, so they still hold values afer exiting from the block; and the interpreter does not complain if a variable is declared twice. For all these reasons, &lt;code&gt;var&lt;/code&gt; is now deprecated, replaced since ES6 (2015) by keywords &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const" rel="noopener noreferrer"&gt;&lt;code&gt;const&lt;/code&gt;&lt;/a&gt; (for variables that do not change after initialization) or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let" rel="noopener noreferrer"&gt;&lt;code&gt;let&lt;/code&gt;&lt;/a&gt; (for mutable variables).&lt;/p&gt;

&lt;p&gt;These new constructs indeed introduced more security in usage of lexical variables in JavaScript: such variables can no longer be used after exiting from the block, and redeclarations raise syntax errors. Yet one ambiguity remains: the shadowing effect of a variable declared with &lt;code&gt;let&lt;/code&gt; does not start at the location of the declaration, but &lt;em&gt;at the beginning of the enclosing block&lt;/em&gt;. This is no longer called "hoisting", but still it means that from the beginning of the block that variable name shadows any variable with the same name in higher scopes. This is called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz" rel="noopener noreferrer"&gt;temporal dead zone&lt;/a&gt; in JavaScript literature.&lt;/p&gt;

&lt;h4&gt;
  
  
  Shadowing is prohibited in Java
&lt;/h4&gt;

&lt;p&gt;Java has no ambiguity with shadowing ... because it has a more radical approach: it raises an exception when a variable is declared in an inner block with a name already in use at a higher scope! The following snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ScopeDemo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;987&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"here x is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" and y is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"here x is "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ScopeDemo.java:6: error: variable x is already defined in method main(String[])
      int x = 123, y = x + 1, z = x + 2;
          ^
1 error
error: compilation failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lexical pragmata
&lt;/h2&gt;

&lt;p&gt;In Perl, lexical scopes are not only used to control the lifetime of lexical variables: they are also used for &lt;em&gt;lexical pragmata&lt;/em&gt; that temporarily alter the behaviour of the interpreter, either by adding some semantics (through the keyword &lt;code&gt;use&lt;/code&gt;) or by removing some semantics (through the keyword &lt;code&gt;no&lt;/code&gt;). Here is an example of one very common idiom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;get_users_from_database&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;no&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uninitialized&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dear &lt;/span&gt;&lt;span class="si"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;-&amp;gt;{firstname} &lt;/span&gt;&lt;span class="si"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;-&amp;gt;{lastname}, bla bla bla&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;At the beginning of the program, the &lt;code&gt;warnings&lt;/code&gt; pragma is activated, because this is general good practice, so that the interpreter can detect suspect situations and warn about them. But when working with a &lt;code&gt;$user&lt;/code&gt; record from the database, some fields might be &lt;code&gt;undef&lt;/code&gt;, which is OK, there is no reason to issue a warning - so &lt;em&gt;within that BLOCK&lt;/em&gt; the interpreter is instructed to treat undefined data as empty strings, without complaining.&lt;/p&gt;

&lt;p&gt;In a similar vein, it is sometimes necessary to alleviate the controls performed by &lt;code&gt;use strict&lt;/code&gt;, in particular on the subject of &lt;a href="https://metacpan.org/pod/strict#strict-refs" rel="noopener noreferrer"&gt;symbolic references&lt;/a&gt;. This control forbids programmatic insertion of new subroutines into the symbol table of a module, a safe measure of prevention; yet this feature is powerful and very useful in some specific situations - so when needed, one can temporarily disable the control:&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;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$method_name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@list_of_names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;no&lt;/span&gt; &lt;span class="nv"&gt;strict&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
  &lt;span class="nv"&gt;*&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$method_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;generate_closure_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$method_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This technique is used quite extensively for example in the Object-Relational Mapping module &lt;a href="https://metacpan.org/pod/DBIx::DataModel" rel="noopener noreferrer"&gt;DBIx::DataModel&lt;/a&gt; for generating methods that implement navigation from one table to another related table. The &lt;a href="https://metacpan.org/dist/DBIx-DataModel/source/lib/DBIx/DataModel/Meta/Utils.pm" rel="noopener noreferrer"&gt;source code&lt;/a&gt; can demonstrate usage patterns.&lt;/p&gt;

&lt;p&gt;Some pragmata can also &lt;em&gt;reinforce&lt;/em&gt; controls instead of alleviating them. One very good example is the &lt;a href="https://metacpan.org/pod/autovivification" rel="noopener noreferrer"&gt;autovivification&lt;/a&gt; module, which changes the default behaviour of Perl on &lt;a href="https://metacpan.org/pod/perlref#Arrow-Notation" rel="noopener noreferrer"&gt;implicit creation of intermediate references&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;my&lt;/span&gt; &lt;span class="nv"&gt;$tree&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                  &lt;span class="c1"&gt;# at this point, $tree is undef&lt;/span&gt;
&lt;span class="nv"&gt;$tree&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# no error; now $tree is {foo =&amp;gt; {bar =&amp;gt; [undef, 99]}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Autovivification can be very handy, but it can be dangerous too. If we want to be on the safe side, we can write&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="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;no&lt;/span&gt; &lt;span class="nv"&gt;autovivification&lt;/span&gt; &lt;span class="sx"&gt;qw/fetch store/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$tree&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                  &lt;span class="c1"&gt;# at this point, $tree is undef&lt;/span&gt;
  &lt;span class="nv"&gt;$tree&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="nv"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# ERROR: Can't vivify reference&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like for lexical variables, lexical pragmata can be nested, the innermost &lt;code&gt;use&lt;/code&gt; or &lt;code&gt;no&lt;/code&gt; declaration temporarily shadowing previous declarations on the same pragma.&lt;/p&gt;

&lt;p&gt;Other examples of lexical pragmata include &lt;a href="https://metacpan.org/pod/bigint" rel="noopener noreferrer"&gt;bigint&lt;/a&gt;, which transparently transforms all arithmetic operations to work with instances of &lt;a href="https://metacpan.org/pod/Math::BigInt" rel="noopener noreferrer"&gt;Math::BigInt&lt;/a&gt;; or the incredible &lt;a href="https://metacpan.org/pod/Regexp::Grammars" rel="noopener noreferrer"&gt;Regexp::Grammars&lt;/a&gt; module that adds grammatical parsing features to Perl regexes. The &lt;a href="https://metacpan.org/dist/perl/view/pod/perlpragma.pod" rel="noopener noreferrer"&gt;perlpragma documentation&lt;/a&gt; explains how module authors can implement new lexical pragmata.&lt;/p&gt;

&lt;h2&gt;
  
  
  'do': transform a BLOCK into an expression
&lt;/h2&gt;

&lt;p&gt;In all examples seen so far, BLOCKs were treated as &lt;em&gt;statements&lt;/em&gt;; but thanks to the &lt;a href="https://metacpan.org/dist/perl/view/pod/perlfunc.pod#do-BLOCK" rel="noopener noreferrer"&gt;do BLOCK&lt;/a&gt; construct, it is also possible to insert a BLOCK anywhere in an expression. The value from the last instruction in the BLOCK is then processed by operators in the expression. This is very convenient for performing a small computation in-place, either for clarity or for efficiency reasons.&lt;/p&gt;

&lt;p&gt;The first example is a cheap version of XML entity encoding, slight adaptation from my module &lt;a href="https://metacpan.org/pod/Excel::ValueWriter::XLSX" rel="noopener noreferrer"&gt;Excel::ValueWriter::XLSX&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;my&lt;/span&gt; &lt;span class="nv"&gt;%ENTITY_TABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;lt;&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;amp;&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$entity_regex&lt;/span&gt; &lt;span class="o"&gt;=&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;my&lt;/span&gt; &lt;span class="nv"&gt;$chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="p"&gt;"",&lt;/span&gt; &lt;span class="nb"&gt;keys&lt;/span&gt; &lt;span class="nv"&gt;%ENTITY_TABLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="sx"&gt;qr/[$chars]/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/($entity_regex)/$ENTITY_TABLE{$1}/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# encode entity characters in $text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second example is from the cousin module &lt;a href="https://metacpan.org/pod/Excel::ValueReader::XLSX" rel="noopener noreferrer"&gt;Excel::ValueReader::XLSX&lt;/a&gt;. Here we are parsing the content of table in an Excel sheet, and the data is returned either in the form of a list of arrayrefs (plain values), or in the form of a list of hashrefs (column name =&amp;gt; value), depending on an &lt;a href="https://metacpan.org/pod/Excel::ValueReader::XLSX#table" rel="noopener noreferrer"&gt;option given by the caller&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;my&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;want_records&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;?&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;my&lt;/span&gt; &lt;span class="nv"&gt;%r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;@r&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@$vals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;%r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                              &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$vals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the caller wants records, the &lt;code&gt;do&lt;/code&gt; block performs a &lt;a href="https://metacpan.org/dist/perl/view/pod/perldata.pod#Slices" rel="noopener noreferrer"&gt;hash slice assignment&lt;/a&gt; into a lexical hash variable to create a new record on the fly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Thanks to BLOCKs, lexical scoping can be introduced very flexibly almost anywhere in Perl code. The semantics of lexical variable and lexical pragmata cleanly defines that the lexical effect starts at the next statement after the declaration, and that it ends at exit from the block, without any of the surprises that we have seen in some other languages. The shadowing effect of lexical variables in inner scopes is easily understandable and consistent across all higher scopes, including the next englobing lexical scopes and the global module scope.&lt;/p&gt;

&lt;p&gt;What a beautiful language design !&lt;/p&gt;

&lt;p&gt;The next post will be about &lt;em&gt;dynamic scoping&lt;/em&gt; through the &lt;code&gt;local&lt;/code&gt; keyword - another, complementary way for temporarily changing the behaviour of the interpreter.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover image
&lt;/h2&gt;

&lt;p&gt;The picture is an excerpt from the initial movement of Verdi's &lt;a href=""&gt;Requiem&lt;/a&gt;, at a place where Verdi &lt;em&gt;shadows&lt;/em&gt; several characteristics of the movement : for a short while, the orchestra stays still, leaving the choir &lt;em&gt;a cappella&lt;/em&gt;, with a different speed, different tonality and different dynamics; then after this parenthesis, all parameters come back to their initial state, &lt;em&gt;come prima&lt;/em&gt; as stated in the score.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
    <item>
      <title>Beautiful Perl features - introduction to the series</title>
      <dc:creator>Laurent Dami</dc:creator>
      <pubDate>Sat, 07 Feb 2026 19:52:54 +0000</pubDate>
      <link>https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-b6a</link>
      <guid>https://dev.to/damil/beautiful-perl-features-introduction-to-the-series-b6a</guid>
      <description>&lt;h2&gt;
  
  
  Expressiveness of the Perl programming language
&lt;/h2&gt;

&lt;p&gt;The collection of features in the Perl programming language is quite unique. Some of these features may seem surprising or even distasteful to people coming from other languages; yet their combination provides a fantastic toolbox for expressiveness in programming, where you can write not only effective, but also &lt;em&gt;beautiful&lt;/em&gt; code.&lt;/p&gt;

&lt;p&gt;True enough, expressivity can also be used for other purposes.  Many years ago, a common entertainment game in the Perl community was the &lt;a href="https://en.wikipedia.org/wiki/Obfuscated_Perl_Contest" rel="noopener noreferrer"&gt;obfuscated Perl contest&lt;/a&gt;, where participants tried to exploit the most arcane parts of the language for producing illegible, yet working programs -- in the same spirit as today's brainrot videos!  People were excited by the creativity potential of Perl. Other productions from that time also include &lt;a href="https://en.wikipedia.org/wiki/Code_golf" rel="noopener noreferrer"&gt;Perl golf&lt;/a&gt;, &lt;a href="https://www.perlmonks.org/?node_id=1111395" rel="noopener noreferrer"&gt;Perl poetry&lt;/a&gt; and Perl haikus.  But apart from fun, if your goals are conciseness, clarity of algorithms and long-term readability, you can use Perl too, with considerable benefits, because the code can be organized so that it closely reflects your thoughts.  This is what I hope to show in this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perl vs other languages : Compare facts, not opinions
&lt;/h2&gt;

&lt;p&gt;Of course using the word "beautiful" in the title is opinionated ... but that is mainly to draw the reader's attention!&lt;/p&gt;

&lt;p&gt;This series will try to focus on &lt;em&gt;factual evidence&lt;/em&gt;, considering in turn various aspects of the Perl programming language and comparing those to similar or dissimilar constructs in other languages (mainly Python, Javascript and Java).  This approach tries to stay away from the vast corpus of opinionated debates about Perl that can be found in many essays, posts or tweets. In most cases such discussions start with a general opinion and then use a few examples to illustrate the argument: under such conditions it is very unlikely that readers will be able to judge for themselves. A more profound comparison of languages requires time, requires details, and requires broad coverage; so here my intention is to go bottom-up, looking at many features of different granularity, so that you can decide for yourself if you find them indeed "beautiful".&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Raku ?
&lt;/h2&gt;

&lt;p&gt;Perl has a sister language now named &lt;a href="https://raku.org/" rel="noopener noreferrer"&gt;Raku&lt;/a&gt;, formerly known as Perl6.  Raku took a very long time to emerge, after a huge participative design effort that carefully discussed weaknesses of Perl and weighed the pros and cons of mechanisms to be incorporated into the new language. Since it was a fresh start, without backwards compatibility constraints, it was possible to freely choose what to keep and what to change.&lt;/p&gt;

&lt;p&gt;The result is more than beautiful, it is awesome and brings Perl's spirit to another dimension ... but unfortunately Raku is still in a niche much smaller than Perl.  Raku really deserves to get a larger audience, and has very qualified advocates for that; but that's not the purpose of the present series, which focuses on Perl5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical notes about Perl fragments in the series
&lt;/h2&gt;

&lt;p&gt;Upcoming posts will discuss various Perl features, in no particular order; some topics are small details, others are fundamental mechanisms.&lt;/p&gt;

&lt;p&gt;Code fragments will be written in modern Perl, namely version 5.42.0, of course with pragmata &lt;a href="https://metacpan.org/pod/strict" rel="noopener noreferrer"&gt;&lt;code&gt;strict&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://metacpan.org/pod/warnings" rel="noopener noreferrer"&gt;&lt;code&gt;warnings&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://metacpan.org/pod/utf8" rel="noopener noreferrer"&gt;&lt;code&gt;utf8&lt;/code&gt;&lt;/a&gt; always activated (even if not repeated in every code fragment).  Subroutine declarations will always use &lt;a href="https://metacpan.org/pod/perlsub#Signatures" rel="noopener noreferrer"&gt;signatures&lt;/a&gt;.  Object-oriented programming will mainly use &lt;a href="https://metacpan.org/dist/perl/view/pod/perlclass.pod" rel="noopener noreferrer"&gt;core classes&lt;/a&gt;, or sometimes &lt;a href="https://metacpan.org/pod/Moose" rel="noopener noreferrer"&gt;Moose&lt;/a&gt; when more sophisticated mechanisms are needed. Yes, this is Perl, there are several ways to do objects !&lt;/p&gt;

&lt;h2&gt;
  
  
  About the author
&lt;/h2&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%2F4c3e3v1mejkjzefvyyqk.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%2F4c3e3v1mejkjzefvyyqk.jpg" title="Picture of me at 'Perl Hof' - a cheese factory in northern Italy :-)" alt="Picture of me at " width="800" height="1253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After 10 years in academia doing research in the field of theory of programming languages, I spent the rest of my career in public administration, using Perl for more than 25 years for a large number of tasks ranging from small, one-shot migration scripts to large enterprise applications or complex data analysis tools. The majority of these applications are still in use today, maintained by a team (contrary to the saying that "Perl code is write-only"), and so rich in features that their replacement by other technology will probably not happen for a while. I have also authored &lt;a href="https://metacpan.org/author/DAMI" rel="noopener noreferrer"&gt;36 modules published on the Comprehensive Perl Archive Network (CPAN)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My knowledge of Java and of Python is mostly theoretical, not consolidated by practical experience, so I apologize in advance if I write inaccurate statements about these languages -- please correct me if this is the case.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the cover image
&lt;/h2&gt;

&lt;p&gt;The picture shows the initial pages of Johann Sebastian Bach's motet &lt;a href="https://en.wikipedia.org/wiki/Singet_dem_Herrn_ein_neues_Lied,_BWV_225" rel="noopener noreferrer"&gt;Singet dem Herrn ein neues Lied&lt;/a&gt;.  In the second half of the XVIIIth century, &lt;a href="https://en.wikipedia.org/wiki/Reception_of_Johann_Sebastian_Bach%27s_music#18th_century" rel="noopener noreferrer"&gt;Bach's style went largely out of fashion&lt;/a&gt; because it was considered too complex, with an "excess of art that altered the beauty of the music".  Common taste at that time preferred the &lt;a href="https://en.wikipedia.org/wiki/Galant_music" rel="noopener noreferrer"&gt;galant style&lt;/a&gt;, with simpler melodies and reduced polyphony.  Bach remained appreciated by a small circle of connoisseurs, though.&lt;/p&gt;

&lt;p&gt;In 1789 when Mozart - already in his maturity - first heard the motet "Singet dem Herrn", he showed great enthusiasm, eagerly asking "what is this" and keen to study "something new at last from which he could learn".  After this episode it took another 50 years before Bach's music started a slow revival, finally leading to his current recognition as one of the greatest composers of all times.&lt;/p&gt;

&lt;p&gt;So Bach is here to remind us that notions of beauty and expressivity, and their relations with complexity or simplicity, may evolve over time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;Many thanks to Boyd Duffee, Matthew O. Persico and Marc Perry who took time to review this material before publication.&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%2Fvlg546n48g8gfx11thon.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%2Fvlg546n48g8gfx11thon.jpg" title="bottle of Perl wine from Bolzen Kellerei, Italy" alt="bottle of Perl wine from Bolzen Kellerei, Italy" width="330" height="465"&gt;&lt;/a&gt;Cheers to Perl!&lt;/p&gt;

</description>
      <category>perl</category>
      <category>programming</category>
      <category>beautifulperl</category>
    </item>
  </channel>
</rss>
