CINXE.COM

The Effective Perler – Effective Perl Programming – write better, more idiomatic Perl

<!DOCTYPE html> <html lang="en-US" class="no-js"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="https://gmpg.org/xfn/11"> <script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script> <title>The Effective Perler &#8211; Effective Perl Programming &#8211; write better, more idiomatic Perl</title> <meta name='robots' content='max-image-preview:large' /> <link rel='dns-prefetch' href='//fonts.googleapis.com' /> <link rel='dns-prefetch' href='//s.w.org' /> <link href='https://fonts.gstatic.com' crossorigin rel='preconnect' /> <link rel="alternate" type="application/rss+xml" title="The Effective Perler &raquo; Feed" href="https://www.effectiveperlprogramming.com/feed/" /> <link rel="alternate" type="application/rss+xml" title="The Effective Perler &raquo; Comments Feed" href="https://www.effectiveperlprogramming.com/comments/feed/" /> <script> window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/13.1.0\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/13.1.0\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/www.effectiveperlprogramming.com\/wp-includes\/js\/wp-emoji-release.min.js?ver=5.9.3"}}; /*! This file is auto-generated */ !function(e,a,t){var n,r,o,i=a.createElement("canvas"),p=i.getContext&&i.getContext("2d");function s(e,t){var a=String.fromCharCode;p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0);e=i.toDataURL();return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),e===i.toDataURL()}function c(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(o=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},r=0;r<o.length;r++)t.supports[o[r]]=function(e){if(!p||!p.fillText)return!1;switch(p.textBaseline="top",p.font="600 32px Arial",e){case"flag":return s([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])?!1:!s([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!s([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]);case"emoji":return!s([10084,65039,8205,55357,56613],[10084,65039,8203,55357,56613])}return!1}(o[r]),t.supports.everything=t.supports.everything&&t.supports[o[r]],"flag"!==o[r]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[o[r]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(n=t.source||{}).concatemoji?c(n.concatemoji):n.wpemoji&&n.twemoji&&(c(n.twemoji),c(n.wpemoji)))}(window,document,window._wpemojiSettings); </script> <style> img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } </style> <link rel='stylesheet' id='wp-block-library-css' href='https://www.effectiveperlprogramming.com/wp-includes/css/dist/block-library/style.min.css?ver=5.9.3' media='all' /> <style id='wp-block-library-theme-inline-css'> .wp-block-audio figcaption{color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-audio figcaption{color:hsla(0,0%,100%,.65)}.wp-block-code>code{font-family:Menlo,Consolas,monaco,monospace;color:#1e1e1e;padding:.8em 1em;border:1px solid #ddd;border-radius:4px}.wp-block-embed figcaption{color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-embed figcaption{color:hsla(0,0%,100%,.65)}.blocks-gallery-caption{color:#555;font-size:13px;text-align:center}.is-dark-theme .blocks-gallery-caption{color:hsla(0,0%,100%,.65)}.wp-block-image figcaption{color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-image figcaption{color:hsla(0,0%,100%,.65)}.wp-block-pullquote{border-top:4px solid;border-bottom:4px solid;margin-bottom:1.75em;color:currentColor}.wp-block-pullquote__citation,.wp-block-pullquote cite,.wp-block-pullquote footer{color:currentColor;text-transform:uppercase;font-size:.8125em;font-style:normal}.wp-block-quote{border-left:.25em solid;margin:0 0 1.75em;padding-left:1em}.wp-block-quote cite,.wp-block-quote footer{color:currentColor;font-size:.8125em;position:relative;font-style:normal}.wp-block-quote.has-text-align-right{border-left:none;border-right:.25em solid;padding-left:0;padding-right:1em}.wp-block-quote.has-text-align-center{border:none;padding-left:0}.wp-block-quote.is-large,.wp-block-quote.is-style-large,.wp-block-quote.is-style-plain{border:none}.wp-block-search .wp-block-search__label{font-weight:700}.wp-block-group:where(.has-background){padding:1.25em 2.375em}.wp-block-separator{border:none;border-bottom:2px solid;margin-left:auto;margin-right:auto;opacity:.4}.wp-block-separator:not(.is-style-wide):not(.is-style-dots){width:100px}.wp-block-separator.has-background:not(.is-style-dots){border-bottom:none;height:1px}.wp-block-separator.has-background:not(.is-style-wide):not(.is-style-dots){height:2px}.wp-block-table thead{border-bottom:3px solid}.wp-block-table tfoot{border-top:3px solid}.wp-block-table td,.wp-block-table th{padding:.5em;border:1px solid;word-break:normal}.wp-block-table figcaption{color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-table figcaption{color:hsla(0,0%,100%,.65)}.wp-block-video figcaption{color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-video figcaption{color:hsla(0,0%,100%,.65)}.wp-block-template-part.has-background{padding:1.25em 2.375em;margin-top:0;margin-bottom:0} </style> <style id='global-styles-inline-css'> body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--dark-gray: #1a1a1a;--wp--preset--color--medium-gray: #686868;--wp--preset--color--light-gray: #e5e5e5;--wp--preset--color--blue-gray: #4d545c;--wp--preset--color--bright-blue: #007acc;--wp--preset--color--light-blue: #9adffd;--wp--preset--color--dark-brown: #402b30;--wp--preset--color--medium-brown: #774e24;--wp--preset--color--dark-red: #640c1f;--wp--preset--color--bright-red: #ff675f;--wp--preset--color--yellow: #ffef8e;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--duotone--dark-grayscale: url('#wp-duotone-dark-grayscale');--wp--preset--duotone--grayscale: url('#wp-duotone-grayscale');--wp--preset--duotone--purple-yellow: url('#wp-duotone-purple-yellow');--wp--preset--duotone--blue-red: url('#wp-duotone-blue-red');--wp--preset--duotone--midnight: url('#wp-duotone-midnight');--wp--preset--duotone--magenta-yellow: url('#wp-duotone-magenta-yellow');--wp--preset--duotone--purple-green: url('#wp-duotone-purple-green');--wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange');--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} </style> <link rel='stylesheet' id='twentysixteen-fonts-css' href='https://fonts.googleapis.com/css?family=Merriweather%3A400%2C700%2C900%2C400italic%2C700italic%2C900italic%7CMontserrat%3A400%2C700%7CInconsolata%3A400&#038;subset=latin%2Clatin-ext&#038;display=fallback' media='all' /> <link rel='stylesheet' id='genericons-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/genericons/genericons.css?ver=20201208' media='all' /> <link rel='stylesheet' id='twentysixteen-style-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/style.css?ver=20201208' media='all' /> <link rel='stylesheet' id='twentysixteen-block-style-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/css/blocks.css?ver=20190102' media='all' /> <!--[if lt IE 10]> <link rel='stylesheet' id='twentysixteen-ie-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/css/ie.css?ver=20170530' media='all' /> <![endif]--> <!--[if lt IE 9]> <link rel='stylesheet' id='twentysixteen-ie8-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/css/ie8.css?ver=20170530' media='all' /> <![endif]--> <!--[if lt IE 8]> <link rel='stylesheet' id='twentysixteen-ie7-css' href='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/css/ie7.css?ver=20170530' media='all' /> <![endif]--> <!--[if lt IE 9]> <script src='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/js/html5.js?ver=3.7.3' id='twentysixteen-html5-js'></script> <![endif]--> <script src='https://www.effectiveperlprogramming.com/wp-includes/js/jquery/jquery.min.js?ver=3.6.0' id='jquery-core-js'></script> <script src='https://www.effectiveperlprogramming.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.3.2' id='jquery-migrate-js'></script> <link rel="https://api.w.org/" href="https://www.effectiveperlprogramming.com/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://www.effectiveperlprogramming.com/xmlrpc.php?rsd" /> <link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://www.effectiveperlprogramming.com/wp-includes/wlwmanifest.xml" /> <meta name="generator" content="WordPress 5.9.3" /> <link type="text/css" rel="stylesheet" href="/wp-content/plugins/syntax-highlighter-and-code-prettifier/styles/shCore.css" /> <link type="text/css" rel="stylesheet" href="/wp-content/plugins/syntax-highlighter-and-code-prettifier/styles/shThemeDefault.css" /> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shCore.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushBash.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushCpp.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushCSharp.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushCss.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushDelphi.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushDiff.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushGroovy.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushJava.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushJScript.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushPerl.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushPhp.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushPlain.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushPython.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushRuby.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushScala.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushSql.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushVb.js"></script> <script type="text/javascript" src="/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/shBrushXml.js"></script> <script type="text/javascript"> SyntaxHighlighter.config.clipboardSwf = '/wp-content/plugins/syntax-highlighter-and-code-prettifier/scripts/clipboard.swf'; SyntaxHighlighter.all(); </script> </head> <body class="home blog wp-embed-responsive group-blog hfeed"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-dark-grayscale"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 0.49803921568627" /><feFuncG type="table" tableValues="0 0.49803921568627" /><feFuncB type="table" tableValues="0 0.49803921568627" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-grayscale"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 1" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-purple-yellow"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.54901960784314 0.98823529411765" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0.71764705882353 0.25490196078431" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-blue-red"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 1" /><feFuncG type="table" tableValues="0 0.27843137254902" /><feFuncB type="table" tableValues="0.5921568627451 0.27843137254902" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-midnight"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 0" /><feFuncG type="table" tableValues="0 0.64705882352941" /><feFuncB type="table" tableValues="0 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-magenta-yellow"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.78039215686275 1" /><feFuncG type="table" tableValues="0 0.94901960784314" /><feFuncB type="table" tableValues="0.35294117647059 0.47058823529412" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-purple-green"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.65098039215686 0.40392156862745" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0.44705882352941 0.4" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-blue-orange"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.098039215686275 1" /><feFuncG type="table" tableValues="0 0.66274509803922" /><feFuncB type="table" tableValues="0.84705882352941 0.41960784313725" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><div id="page" class="site"> <div class="site-inner"> <a class="skip-link screen-reader-text" href="#content">Skip to content</a> <header id="masthead" class="site-header"> <div class="site-header-main"> <div class="site-branding"> <h1 class="site-title"><a href="https://www.effectiveperlprogramming.com/" rel="home">The Effective Perler</a></h1> <p class="site-description">Effective Perl Programming &#8211; write better, more idiomatic Perl</p> </div><!-- .site-branding --> <button id="menu-toggle" class="menu-toggle">Menu</button> <div id="site-header-menu" class="site-header-menu"> <nav id="site-navigation" class="main-navigation" aria-label="Primary Menu"> <div class="menu-menu-container"><ul id="menu-menu" class="primary-menu"><li id="menu-item-2706" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2706"><a href="https://www.effectiveperlprogramming.com/toc/">TOC</a></li> <li id="menu-item-2707" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2707"><a href="https://www.effectiveperlprogramming.com/errata/">Errata</a></li> <li id="menu-item-2708" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2708"><a href="https://www.effectiveperlprogramming.com/about/">About</a></li> </ul></div> </nav><!-- .main-navigation --> </div><!-- .site-header-menu --> </div><!-- .site-header-main --> </header><!-- .site-header --> <div id="content" class="site-content"> <div id="primary" class="content-area"> <main id="main" class="site-main"> <article id="post-2710" class="post-2710 post type-post status-publish format-standard hentry category-5-36 category-new-features"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/11/perl-v5-36-new-features/" rel="bookmark">Perl v5.36 new features</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> These items are in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.</p> <p><br clear="all"/></p> <ul> <li>Unicode 14</li> <li><code>use v5.36</code> now disables <code>indirect</code> and <code>multidimensional</code></li> <li><a href="/2024/10/switch-removed-f…6-feature-bundle/">switch removed from v5.36 feature bundle</a></li> <li><a href="/2024/09/know-if-something-is-a-boolean/">Pure booleans</a></li> <li><A href="/2024/07/automatically-turn-on-warnings/"><code>use v5.36</code> enables warnings</a></li> <li>More paired delimiters</li> <li><code>finally</code> blocks</li> <li><a href="/2015/04/use-v5-20-subroutine-signatures/">subroutine signatures are no longer experimental</a></li> <li><code>@_</code> is now experimental within signatured subs</li> <li><a href="/2020/01/use-the-infix-class-instance-operator/">The <code>isa</code> operator is no longer experimental</a></li> <li><a href="/2024/08/slurp-a-file-from-the-command-line-with-g/">the <code>-g</code> command-line flag is a shortcut for -0777</a></li> <li><a href="/2024/06/iterate-over-multiple-elements-at-the-same-time/">experimental iteration of multiple values</a></li> <li><code>defer</code> blocks</li> </ul> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/11/perl-v5-36-new-features/" rel="bookmark"><time class="entry-date published updated" datetime="2024-11-15T12:32:07+00:00">November 15, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/perl/new-features/" rel="category tag">new features</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2710 --> <article id="post-2824" class="post-2824 post type-post status-publish format-standard hentry category-5-36 category-removed-features"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/11/goodbye-fake-multidimensional-data-structures/" rel="bookmark">Goodbye fake multidimensional data structures</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.<br /> <br clear="all"/></p> <hr/> <p>Perl v5.36 disables by default a Perl 3 feature that you may have never seen, which I&#8217;ll cover in the next section. In a single-element access to a hash, you were able to use a list of indices to simulate a multidimensional data structure. This was long before Perl had references (and shortly before Taylor Swift was born). Yet, in v5.34, this still works:</p> <pre class="brush:perl"> use v5.34; my %hash; $hash{1,3} = 7; # modern way is $array[1][3] = 7; </pre> <p>In v5.36, this still works as long as you specify a minimum Perl version with <code>require</code> instead of <code>use</code>:</p> <pre class="brush:perl"> require v5.36; my %hash; $hash{1,3} = 7; </pre> <p>With <code>use</code>, though, Perl loads the appropriate feature bundle, which turns off this feature:</p> <pre class="brush:perl"> use v5.36; my %hash; $hash{1,3} = 7; </pre> <p>The output shows that the <code>multidimensional</code> feature was removed from the list:</p> <pre class="brush:plain"> Multidimensional hash lookup is disabled at ... Execution of ... aborted due to compilation errors. </pre> <p>This version also disables <A href="/2024/10/switch-removed-f…6-feature-bundle/"><code>switch</code></a> and <a href="/2020/06/turn-off-indirect-object-notation/"><code>indirect</code></a>.</p> <p>Enable <code>multidimensional</code> explicitly if you want to restore it, although you should only do this for legacy code since the feature is likely disappear completely:</p> <pre class="brush:perl"> use v5.36; use warnings; use feature qw(multidimensional); </pre> <h2>Perl 4&#8217;s fake multidimensional hashes</h2> <p>Perl 4 did not have references, so it didn&#8217;t have a way include an array in an array. However, you could fake it with a special hash<br /> key convention that Perl stole from Awk.</p> <p>To make this work, you access a single element in the hash, but have a &#8220;list&#8221; of comma-separated index values as the hash key:</p> <pre class="brush:perl"> my %hash; $hash{0,0} = "a"; $hash{1,1} = "b"; for( my $row = 0; $row <= 1; $row++ ) { for( my $col = 0; $col <= 1; $col++ ) { printf '% 2s', $hash{$row,$col} // 0; } print "\n"; } </pre> <p>This outputs your tiny matrix:</p> <pre class="brush:plain"> a 0 0 b </pre> <p>To see what Perl is doing, dump that hash. The <code>$Useqq</code> variable from <a href="https://metacpan.org/pod/Data::Dumper">Data::Dumper</a> encodes unprintables as their ordinal values in octal"</p> <pre class="brush:perl"> $Data::Dumper::Useqq = 1; say Dumper(\%hash); </pre> <pre class="brush:plain"> $VAR1 = { "0\0340" => "a", "1\0341" => "b" }; </pre> <p>That <code>\034</code> is (U+001C INFORMATION SEPARATOR FOUR):</p> <pre class="brush:perl"> printf '% 2s', $hash{ "$row\034$col" } // 0; </pre> <p>Perl calls that <code>$;</code> (or <code>$SUBSCRIPT_SEPARATOR</code> or <code>$SUBSEP</code>). Larry had wanted to use <code>$,</code> but that was already the output field separator. You can use this value directly:</p> <pre class="brush:perl"> printf '% 2s', $hash{ "$row$;$col" } // 0; </pre> <p>You can mix the forms too. This examples assigns with the comma notation but outputs it by constructing the key itself:</p> <pre class="brush:perl"> $row = 1; $col = 3; $hash{$row,$col} = 7; printf '% 2s', $hash{ "$row$;$col" } // 0; </pre> <h2>Change the separator</h2> <p>If <code>\034</code> is something that might appear in your data, change the multidimensional separator to something that won't conflict:</p> <pre class="brush:perl"> local $; = '\000' </pre> <h2>From the Perl documentation</h2> <ul> <li><a href="https://perldoc.perl.org/perlsyn">perlsyn</a></li> <li><a href="https://perldoc.perl.org/perlvar">perlvar</a></li> </ul> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/11/goodbye-fake-multidimensional-data-structures/" rel="bookmark"><time class="entry-date published" datetime="2024-11-14T10:21:39+00:00">November 14, 2024</time><time class="updated" datetime="2024-11-09T12:07:54+00:00">November 9, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/perl/removed-features/" rel="category tag">removed features</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2824 --> <article id="post-2812" class="post-2812 post type-post status-publish format-standard hentry category-5-36 category-miscellany category-removed-features"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/10/switch-removed-from-the-v5-36-feature-bundle/" rel="bookmark">switch removed from the v5.36 feature bundle</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.<br /> <br clear="all"/></p> <hr/> <p>We&#8217;re almost at the end of the tragic saga of <code>given-when</code>, a feature added in v5.10. <A href="/2016/04/lexical-_-and-autoderef-are-gone-in-v5-24/">It lost the lexical <code>$_</code> in v5.24</a> after that feature was demoted to experimental in v5.14. Smart matching, almost the entire point of <code>given-when</code>, has already been demoted to experimental status. Then, <A href="/2017/12/beware-of-the-removal-of-when-in-perl-v5-28/">v5.28 flirted with removing <code>given-when</code></a> before deciding that was too hasty. It&#8217;s been awhile, and it&#8217;s on to the next step.</p> <p>The latest humiliation is that the <code>switch</code> feature (really <code>given-when</code>) is longer part of the list of the default features enabled by requiring a version of perl, as in <code>use v5.26;</code>. </p> <p>The feature is still there if you want to use it, but you need to explicitly enable it:</p> <pre class="brush:perl"> use feature qw(switch); </pre> <p>But, don&#8217;t start using this feature now. You&#8217;ve had plenty of time to fix it and you can <a href="/2011/05/use-for-instead-of-given/">get most of what you need using <code>for</code> instead</a>.</p> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/10/switch-removed-from-the-v5-36-feature-bundle/" rel="bookmark"><time class="entry-date published" datetime="2024-10-14T07:31:13+00:00">October 14, 2024</time><time class="updated" datetime="2024-09-28T06:28:18+00:00">September 28, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a>, <a href="https://www.effectiveperlprogramming.com/category/perl/removed-features/" rel="category tag">removed features</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2812 --> <article id="post-2800" class="post-2800 post type-post status-publish format-standard hentry category-5-36 category-miscellany"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/09/know-if-something-is-a-boolean/" rel="bookmark">Know if something is a boolean</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.<br /> <br clear="all"/></p> <hr/> <p>So far, Perl has not had special boolean values. Perl doesn&#8217;t even have a strictly true value; it has specified false values (<code>0</code>, <code>'0'</code>, empty string, and <code>undef</code>), and everything that is not false is true. Not only that, by using strings or numbers (or undef) interchangeably and output stringifying everything, Perl can&#8217;t tell how it should represent the value in formats that have particular ideas about booleans, but now there&#8217;s something that can help with that.</p> <p>Through <a href="https://metacpan.org/pod/builtin">builtin</a>, v5.36 adds <code>true</code> and <code>false</code> functions and a way for you to know that a value is a boolean. This allows you to represent these values correctly for other formats.</p> <p>Before you get too excited, Perl may have these features but your favorite libraries probably aren&#8217;t using them yet. Some of those have special ways to represent these, and they&#8217;ll probably aren&#8217;t going to change since they have to support the old and new ways.</p> <h2>A JSON example</h2> <p>Consider this JSON, which has <code>true</code> and <code>false</code>:</p> <pre class="brush:plain"> { "updated": true, "paid": false } </pre> <p>Now look at what happens when you encode plain, non-special Perl values as JSON. Take the Perl true and false values from the results of some comparisons:</p> <pre class="brush:perl"> use v5.10; use JSON; my $true = (1==1); my $false = (0==1); my $data = { "updated" => $true, "paid" => $false }; my $json = encode_json($data); say $json; </pre> <p>The output shows that Perl created both JSON values as strings, and the false value is the empty string. Perl dumbly stringifies everything as best if can since it doesn&#8217;t know about fine-grained types:</p> <pre class="brush:plain"> {"updated":"1","paid":""} </pre> <p>This means that any external JSON parsers will not correctly find JSON&#8217;s <code>true</code> or <code>false</code> values. The string <code>"1"</code> is no more special than any other string:</p> <pre class="brush:plain"> $ echo '{"updated":"1","paid":""}' |⏎jq '. | select(.updated == true)' </pre> <p>With JSON&#8217;s <code>true</code> value, the filter works:</p> <pre class="brush:plain"> $ echo '{"updated":true,"paid":false}' |⏎jq '. | select(.updated == true)' { "updated": true, "paid": false } </pre> <p>Perl&#8217;s <a href="https://metacpan.org/pod/JSON">JSON</a> module solves this by using special references so it knows that there is a boolean value. Instead of Perl&#8217;s squiggly true or false values, it uses references to either <code>1</code> or <code>0</code>, which it then turns into special internal objects:</p> <pre class="brush:perl"> use v5.10; use JSON; my $true = \1; my $false = \0; my $data = { "updated" => $true, "paid" => $false }; my $json = encode_json($data); say $json; </pre> <p>Now the output is what JSON expects:</p> <pre class="brush:plain"> {"updated":true,"paid":false} </pre> <p>Going the other way, from JSON to a Perl structure, dumping the values shows how <a href="https://metacpan.org/pod/JSON">JSON</a> uses special objects:</p> <pre class="brush:perl"> use v5.10; use JSON; my $json = qq({ "updated": true, "paid": false }); my $data = decode_json($json); use Data::Dumper; say Dumper($data); </pre> <p>The output shows that <a href="https://metacpan.org/pod/JSON">JSON</a> uses a special class, <code>JSON::PP::Boolean</code>, where the object value is a reference to Perl&#8217;s false or non-false values:</p> <pre class="brush:plain"> $VAR1 = { 'updated' => bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ), 'paid' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' ) }; </pre> <p>This is one of the cures for people who want types. As long as the object can handle the behavior, you don&#8217;t care what it actually is.</p> <h2>true and false</h2> <p>Through the new <code>builtin</code>, Perl v5.36 adds the new functions <code>true</code> and <code>false</code>. These are &#8220;distinguished&#8221; boolean values because they are explicitly for boolean operations. You can use these anywhere you&#8217;d use any of Perl&#8217;s false or non-false values. For example, in a <code>while</code> conditional:</p> <pre class="brush:perl"> use v5.36; use builtin qw(true false); use experimental qw(builtin); while( true ) { state $count = 0; say $count; last if $count++ > 3; } </pre> <p>Under the hood, the &#8220;distinguished&#8221; boolean values have an extra <code>BOOL</code> flag. In this program, the first two boolean values are the new special values and the last one is just a plain <code>"1"</code>:</p> <pre class="brush:perl"> use v5.36; use builtin qw(true false); use experimental qw(builtin); use Devel::Peek; my $from_function = true; Dump($from_function); my $from_eq = 'a' eq 'b'; Dump($from_eq); my $from_one = "1"; Dump($from_one); </pre> <p><a href="https://metacpan.org/pod/Devel::Peek">Devel::Peek</a> shows that the first two values have a <code>BOOL</code> flag. Compare those to the last dump, which does not have the boolean value:</p> <pre class="brush:plain"> SV = PVNV(0x7fcd72809850) at 0x7fcd74008b00 REFCNT = 1 FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK) IV = 1 NV = 1 PV = 0x106f29ac3 "1" [BOOL PL_Yes] CUR = 1 LEN = 0 SV = PVNV(0x7fcd72809990) at 0x7fcd74008a88 REFCNT = 1 FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK) IV = 0 NV = 0 PV = 0x106f29ac5 "" [BOOL PL_No] CUR = 0 LEN = 0 SV = PV(0x7fcbeb00b050) at 0x7fcbeb86e408 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x600003bd9930 "1"\0 CUR = 1 LEN = 10 COW_REFCNT = 1 </pre> <h2>Testing for a boolean</h2> <p>The previous section showed that Perl now tracks a difference between distinguished booleans and the &#8220;normal&#8221; truthy values. Along with the new <code>true</code> and <code>false</code> values, <a href="https://metacpan.org/pod/builtin">builtin</a> also provides <code>is_bool</code> so you can tell the difference between these new values ane &#8220;normal&#8221; values:</p> <pre class="brush:perl"> use v5.36; use builtin qw(true false is_bool); use experimental qw(builtin); my $from_function = true; say is_bool($from_function) ? 'boolean' : 'not boolean'; my $from_eq = 'a' eq 'b'; say is_bool($from_eq) ? 'boolean' : 'not boolean'; my $from_one = "1"; say is_bool($from_one) ? 'boolean' : 'not boolean'; </pre> <p>The <code>is_bool</code> returns true for the first two, but false for the last one:</p> <pre class="brush:plain"> boolean boolean not boolean </pre> <h3>Maintaining boolean status</h3> <p>If Perl can track boolean status, how would a value lose it? Or maybe, gain it? Comparisons return boolean values. Negation (and double negation) return distinguished booleans. Mathematical and string operations lose the <code>BOOL</code> flag. Here&#8217;s a program to demonstrate various situations:</p> <pre class="brush:perl"> use v5.36; use builtin qw(true false is_bool); use experimental qw(builtin); sub check ( $v ) { is_bool( $v ) ? 'boolean' : 'not boolean' } my $format = "%13s is %s\n"; printf $format, "1", check( 1 ); printf $format, "0", check( 0 ); printf $format, "!1", check( ! 1 ); printf $format, "!0", check( ! 0 ); printf $format, "!!1", check( !! 1 ); printf $format, "!!0", check( !! 0 ); printf $format, "1 == 1", check( 1 == 1 ); printf $format, "'a' eq 'b'", check( 'a' eq 'b' ); printf $format, "true", check( true ); printf $format, "false", check( false ); printf $format, "0 + true", check( 0 + true ); printf $format, "0 + false", check( 0 + false ); printf $format, "'' . true", check( '' . true ); printf $format, "'' . false", check( '' . false ); printf $format, "true == true", check( true == true ); printf $format, "true eq false", check( true eq false ); </pre> <p>The output shows what has the <code>BOOL</code> flag and what doesn&#8217;t:</p> <pre class="brush:plain"> 1 is not boolean 0 is not boolean !1 is boolean !0 is boolean !!1 is boolean !!0 is boolean 1 == 1 is boolean 'a' eq 'b' is boolean true is boolean false is boolean 0 + true is not boolean 0 + false is not boolean '' . true is not boolean '' . false is not boolean true == true is boolean true eq false is boolean </pre> <h2>Further reading</h2> <ul> <li><A href="https://github.com/Perl/PPCs/blob/main/ppcs/ppc0008-sv-boolean-type.md">PPC 8: Stable SV Boolean Type</a></li> </ul> <h2>From the Perl documentation</h2> <ul> <li><a href="https://metacpan.org/pod/builtin">builtin</a></li> <li><a href="https://github.com/Perl/PPCs/pull/3">PPC describing SV boolean semantics</a></li> </ul> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/09/know-if-something-is-a-boolean/" rel="bookmark"><time class="entry-date published" datetime="2024-09-15T07:31:52+00:00">September 15, 2024</time><time class="updated" datetime="2024-08-15T15:46:07+00:00">August 15, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2800 --> <article id="post-2794" class="post-2794 post type-post status-publish format-standard hentry category-5-36 category-miscellany"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/08/slurp-a-file-from-the-command-line-with-g/" rel="bookmark">Slurp a file from the command line with -g</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.<br /> <br clear="all"/></p> <hr/> <p>Perl v5.36 adds the <code>-g</code> switch as a shortcut for <code>-0777</code>, which undefines the input record separator so you can read an entire file as a single string. This is often called &#8220;slurping&#8221;, and is useful when you need to process text that spans several lines.</p> <h2>The input record separator</h2> <p>The input record separator is the character (or characters) that Perl&#8217;s line-input operator uses to determine when a line has ended. By default, that&#8217;s a newline (U+0010), but you can use any string you like by setting <code>$/</code> (<code>$INPUT_RECORD_SEPARATOR</code>). Sometimes the form feed is a useful separator for multiline records:</p> <pre class="brush:perl"> $/ = "\f"; </pre> <p>On the command line, the <code>-0</code> switch is a quick way to set the value for <code>$/</code>. Without a value, it uses the null byte, which is sometimes a useful as a separator:</p> <pre class="brush:plain"> % perl -MO=Deparse -0 -e 1 BEGIN { $/ = "\000"; $\ = undef; } '???'; -e syntax OK </pre> <p>A number in octal or hexadecimal sets <code>$/</code> to some other single character:</p> <pre class="brush:plain"> % perl -MO=Deparse -0014 -e 1 BEGIN { $/ = "\f"; $\ = undef; } '???'; -e syntax OK </pre> <pre class="brush:plain"> % perl -MO=Deparse -0xC -e 1 BEGIN { $/ = "\f"; $\ = undef; } '???'; -e syntax OK </pre> <p>Any number above 0377 octal (more than 255 decimal) sets <code>$/</code> to undef:</p> <pre class="brush:plain"> % perl -MO=Deparse -0377 -e 1 BEGIN { $/ = "\377"; $\ = undef; } '???'; -e syntax OK </pre> <pre class="brush:plain"> % perl -MO=Deparse -0400 -e 1 BEGIN { $/ = undef; $\ = undef; } '???'; -e syntax OK </pre> <p>Conventionally, though, the Perl documentation has used <code>777</code> as the value to get undef probably since it&#8217;s easier to remember:</p> <pre class="brush:plain"> % perl -MO=Deparse -0777 -e 1 BEGIN { $/ = undef; $\ = undef; } '???'; -e syntax OK </pre> <p>The new <code>-g</code> is a short synonym for <code>-0777</code>, so it does the same thing that :</p> <pre class="brush:plain"> % perl -MO=Deparse -e 1 '???'; -e syntax OK </pre> <pre class="brush:plain"> % perl -MO=Deparse -g -e 1 BEGIN { $/ = undef; $\ = undef; } '???'; -e syntax OK </pre> <h2>Far more than you ever wanted to know</h2> <p>The <code>-0</code> switch has some other interesting behavior, and has a few other interesting features. Since I&#8217;m already writing about this feature, I might as well keep going.</p> <h3>Single-character line ending</h3> <p>You can use an octal or hexadecimal number after the <code>-0</code> to choose the single character that you want to use as the line ending. I&#8217;ve often used the form feed (U+000C) to separate multi-line records. The particular character doesn&#8217;t matter as long as it doesn&#8217;t appear in the data (so the null byte might be useful too):</p> <pre class="brush:plain"> % perl -le "print qq(one\ntwo\nthree\n\fA\nB\nC\n\f9\n10\n11\n)" > formfeed.txt </pre> <p>When you read F<formfeed.txt> by lines with no change to the input record separator, you see the three records separated by &#8220;blank&#8221; lines, which are really the form feed:</p> <pre class="brush:plain"> % perl -ne 'print' formfeed.txt one two three A B C 9 10 11 </pre> <p>You can see that easier when you replace the invisible characters with their ordinal values, which you do in octal here:</p> <pre class="brush:plain"> % perl -pe 's/(\P{Print})/sprintf(q(%03o),ord($1)) . "\n"/eg' formfeed.txt one012 two012 three012 014 A012 B012 C012 014 9012 10012 11012 012 </pre> <p>When you use the octal value of the form feed for the number after the <code>-0</code> switch and output lines surrounded by angle brackets, you get three lines (with the newlines and line-ending form feed in tact):</p> <pre class="brush:plain"> % perl -014 -ne 'print qq(&lt;$_>)' formfeed.txt &lt;one two three >&lt;A B C >&lt;9 10 11 > </pre> <p>You could have also specified this with three digits, <code>-0014</code>, or as hexadecimal with a leading <code>x</code>, like <code>-0xC</code>. The hexadecimal version is valuable when you need to specify a character past the largest single octet value you can get out of three octal digits, which is <code>0377</code>.</p> <p>There&#8217;s a catch though. If you want to set the input record separator to a wide character, you need to ensure that you read the input correctly. For the ☃ (U+2603 SNOWMAN) to be the separator, which takes up three octets in UTF-8, you need to read the input as UTF-8 too. The <code>-C</code> is one way to do that:</p> <pre class="brush:plain"> % perl -0x2603 -C -ne 'print qq(&lt;$_>)' snowmen.txt >> </pre> <p>You aren&#8217;t able to specify multiple characters as a line separator since B<perl> thinks the extra characters are a file for input:</p> <pre class="brush:plain"> % perl -MO=Deparse -0x0100x2603 -e No Perl script found in input </pre> <h2>Slurping an entire file</h2> <p>If you specify an octal value 400 or higher, which is more than 8 bits, Perl sets the input record separator to undef. With no defined value for <code>$/</code>, Perl slurps the entire input. But, this is different than setting the empty string (a defined value), which I write about in the next section.</p> <p>You&#8217;ve probably seen <code>-0777</code>, perhaps the most common use of <code>-0</code>:</p> <pre class="brush:plain"> % perl -0777 -ne 'print qq(&lt;$_>)' dog.txt &lt;Newfoundland Golden Retreiver Boxer > </pre> <p>That F<dog.txt> is actually read through the <code>ARGV</code> filehandle, which does some trickery to make it look like all the input is coming from one source. However, the line input operator can&#8217;t read across the command line files; B<perl> figures out when one file is empty, closes it, then opens the next file. So, each file appears to be its own line:</p> <pre class="brush:plain"> % perl -0777 -ne 'print qq(&lt;$_>)'⏎dog.txt cat.txt lizard.txt &lt;Newfoundland Golden Retreiver Boxer >&lt;Tabby Marmalade Tiger >&lt;Monitor Iguana Godzilla > </pre> <p>If you wanted all the files to be one lines, route them through standard input before they get to B<perl>. This only looks like a useless use of B<cat>:</p> <pre class="brush:plain"> % cat dog.txt cat.txt lizard.txt |⏎perl -0 -ne 'print qq(<$_>)' </pre> <p>=head1 Paragraph mode</p> <p>&#8220;Paragraph mode&#8221; is a special case. The <code>-00</code> sets the input record separator to the empty string. That&#8217;s different than the undefined value even though both are false:</p> <pre class="brush:plain"> % perl -MO=Deparse -00 -e 1 BEGIN { $/ = ""; $\ = undef; } '???'; -e syntax OK </pre> <p>When the input record separator is the empty string, B<perl> treats it as if it is multiple consecutive newlines. This has the same effect as if the input record separator were the pattern <code>\n+</code> Not only that, put it collapses the multiple newlines to exactly two newlines:</p> <pre class="brush:plain"> % perl -00 -ne 'print qq(&lt;$_>)' paras.txt &lt;First line first para Second line first para Third line first para >&lt;After first blank line Second line after first blank line Third line after first blank line >&lt;After 2nd blank line 2nd line after 2nd blank line 3rd line after 2nd blank line > </pre> <h2>Summary</h2> <p>Here&#8217;s a quick summary of the various incantations of the <code>-0</code> switch:</p> <table> <tr> <th>Switch</th> <th>Input Record Separator</th> <th>Note</th> </tr> <tr> <td><code>-0</code></td> <td><code>\000</code></td> <td>null byte</td> </tr> <tr> <td><code>-00</code></td> <td>empty string, but &#8220;\n+&#8221;</td> <td>paragraph mode</td> </tr> <tr> <td><code>-0014</code></td> <td>8-bit character, in octal</td> <td>form feed</td> </tr> <tr> <td><code>-0xC</code></td> <td>8-bit character, in hex</td> <td>form feed</td> </tr> <tr> <td><code>-0400</code></td> <td>undef, above 8-bit</td> <td>slurp</td> </tr> <tr> <td><code>-0777</code></td> <td>undef, idiomatic</td> <td>slurp</td> </tr> <tr> <td><code>-g</code></td> <td>undef</td> <td>slurp, new in v5.36</td> </tr> <tr> <td><code>-0x1FF</code></td> <td><code>\777</code> character, include <code>-C</code></td> <td>actual <code>\777</code></td> </tr> <tr> <td><code>-0x2603</code></td> <td>wide character, include <code>-C</code></td> <td>snowman</td> </tr> </table> <h2>From the Perl documentation</h2> <ul> <li><a href="https://perldoc.perl.org/perlrun">perlrun</a></li> </ul> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/08/slurp-a-file-from-the-command-line-with-g/" rel="bookmark"><time class="entry-date published" datetime="2024-08-15T00:00:44+00:00">August 15, 2024</time><time class="updated" datetime="2024-07-22T20:50:44+00:00">July 22, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2794 --> <article id="post-2718" class="post-2718 post type-post status-publish format-standard hentry category-5-36 category-warnings"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/07/automatically-turn-on-warnings/" rel="bookmark">Automatically turn on warnings</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"/> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.</p> <hr /> <p><br clear="all"/></p> <p>Perl v5.36 automatically turns on <code>warnings</code> when you specify the minimum Perl version with <code>use</code>:</p> <pre class="brush:perl"> use v5.36; # use warnings for free </pre> <p>Since this form has been turning on strictures since v5.12 (<a href="https://www.effectiveperlprogramming.com/2010/08/implicitly-turn-on-strictures-with-perl-5-12/">Implicitly turn on strictures with Perl 5.12</a>), you no longer have to specify warnings or strict at the top of my program.</p> <p> <a href="https://www.effectiveperlprogramming.com/2024/07/automatically-turn-on-warnings/#more-2718" class="more-link">Continue reading<span class="screen-reader-text"> &#8220;Automatically turn on warnings&#8221;</span></a></p> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/07/automatically-turn-on-warnings/" rel="bookmark"><time class="entry-date published" datetime="2024-07-22T19:10:29+00:00">July 22, 2024</time><time class="updated" datetime="2024-09-28T06:00:47+00:00">September 28, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/warnings/" rel="category tag">warnings</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2718 --> <article id="post-2716" class="post-2716 post type-post status-publish format-standard hentry category-5-36 category-5-38 category-miscellany"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/06/iterate-over-multiple-elements-at-the-same-time/" rel="bookmark">Iterate over multiple elements at the same time</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.<br /> <br clear="all"/></p> <hr/> <p><i>This feature was promoted to a stable version in <a href="/2024/05/perl-v5-40-new-features/">v5.40</a>.</i></p> <p>Perl v5.36 adds experimental support that allows a <code>foreach</code> (or <code>for</code>) to loop iterate over multiple values at the same time by specifying multiple control variables. This is incredibly cool:</p> <pre class="brush:perl"> use v5.36; use experimental qw(for_list); my @animals = qw( Buster Mimi Ginger Nikki ); foreach my( $s, $t ) ( @animals ) { say "$s ^^^ $t"; } </pre> <p>The output shows two iterations of the loop, each which grabbed two values from the list:</p> <pre class="brush:plain"> Buster ^^^ Mimi Ginger ^^^ Nikki </pre> <p>Add another parameter; the list now doesn&#8217;t divide evenly between the parameters, so any parameter that can&#8217;t match with a list item gets <code>undef</code>, just like normal list assignment:</p> <pre class="brush:perl"> use v5.36; use experimental qw(for_list); foreach my( $s, $t, $u ) ( @animals ) { say "$s ^^^ $t ^^^ $u"; } </pre> <p>Since <a href="/2024/07/automatically-turn-on-warnings/"><code>use v5.36</code> also turns on warnings</a>, you get those &#8220;uninitialized&#8221; warnings for free when you use those <code>undef</code> values:</p> <pre class="brush:plain"> Buster ^^^ Mimi ^^^ Ginger Nikki ^^^ ^^^ Use of uninitialized value ... Use of uninitialized value ... </pre> <p>Another interesting use combines the new <code>builtin::indexed</code> feature that gets you the index and value at the same time:</p> <pre class="brush:perl"> use v5.36; use experimental qw(for_list builtin); use builtin qw(indexed); my @animals = qw( Buster Mimi Ginger Nikki ); foreach my( $i, $value ) ( indexed(@animals) ) { say "$i: $value"; } </pre> <p>That&#8217;s a bit nicer than going through the indices to access the value in an additional statement:</p> <pre class="brush:perl"> foreach my $i ( 0 .. $#animals ) { my $value = $animals[$i]; say "$i: $value"; } </pre> <h2>No placeholders (yet)</h2> <p>So far, this new syntax doesn&#8217;t have a way to skip values. In a normal list assignment, you discard a value coming from the right hand list with a literal <code>undef</code>:</p> <pre class="brush:perl"> my( $s, undef, $t ) = @animals </pre> <p>Try that in the <code>for</code> list and you get a syntax error:</p> <pre class="brush:perl"> foreach my( $s, undef, $u ) ( @animals ) { # ERROR! say "$s ^^^ $u"; } </pre> <h2>Hash keys and values</h2> <p>I&#8217;m tempted to use this for hashes, although <code>each</code> inside a <code>while</code> is still probably better since it doesn&#8217;t have to build the entire input list in one go:</p> <pre class="brush:perl"> use experimental qw(for_list); my %animals = ( cats => [ qw( Buster Mimi Ginger ) ], dogs => [ qw( Nikki ) ], ); foreach my( $k, $v ) ( %animals ) { say "$k ^^^ @$v"; } </pre> <p>Since those hash values are array refs, it would be helpful if this feature could use the <code>refaliasing</code> and <code>declared_refs</code> features (<a href="/2018/09/mix-assignment-and-reference-aliasing-with-declared_refs/">Mix assignment and reference aliasing with declared_refs</a>):</p> <pre class="brush:perl"> use experimental qw(for_list); use experimental qw(refaliasing declared_refs); my %animals = ( cats => [ qw( Buster Mimi Ginger ) ], dogs => [ qw( Nikki ) ], ); foreach my( $k, \@v ) ( %animals ) { say "$k ^^^ @v"; } </pre> <p>Sadly, the parser doesn&#8217;t expect the reference operator inside that <code>for</code> list:</p> <pre class="brush:plain"> syntax error ... near ", \" </pre> <h2>Doing</h2> <p>Prior to builtin multiple iteration, the best way to do the same thing was probably the <A href="https://metacpan.org/pod/List::MoreUtils">List::MoreUtils</a> (not part of core) module. The <code>natatime</code> function, which I wished was named <code>n_at_a_time</code>, grabs the number of elements that you specify and returns them as a list. Since it returns a list instead of an array reference, it&#8217;s easier to use it with a <code>while</code>:</p> <pre class="brush:perl"> use List::MoreUtils qw(natatime); my @x = ('a' .. 'g'); my $iterator = natatime 3, @x; while( my @vals = $iterator->() ) { print "@vals\n"; } </pre> <p>Another approach uses <code>splice</code>. The easiest thing might be to do it destructively since that requires no index fiddling:</p> <pre class="brush:perl"> my @x = 'a' .. 'g'; my @temp = @x; while( my @vals = splice @temp, 0, 3, () ) { print "@vals\n"; } </pre> <p>Here&#8217;s an example from the L<splice> documentation that does the same thing:</p> <pre class="brush:perl"> sub nary_print { my $n = shift; while (my @next_n = splice @_, 0, $n) { say join q{ -- }, @next_n; } } nary_print(3, qw(a b c d e f g h)); # prints: # a -- b -- c # d -- e -- f # g -- h </pre> <p>Playing with the array indices can get this done, but it comes with a lot of baggage. First, an array slice doesn&#8217;t return an empty list, so you can&#8217;t use that as a condition in the <code>while</code> as in the previous examples. Since it fills in the missing elements with <code>undef</code>, outputting the values possibly comes with warnings. Even if you want to accept those annoyances, you still have to manage the end of array condition (<code>$#X</code>) yourself:</p> <pre class="brush:perl"> my @x = 'a' .. 'g'; my $start = 0; my $n = 3; while( $start <= $#x ) { no warnings qw(uninitialized); my @vals = @x[$start, $start + $n - 1]; print "@vals\n"; $start += $n; } </pre> <p>So yeah, having a multiple iterator feature built into Perl is a huge win.</p> <h2>Summary</h2> <p>The experimental <code>for_list</code> feature lets you take multiple elements of the list in each iteration. This doesn't yet handle many of the list assignment features that would make this as useful as people will want it to be.</p> <h2>From the Perl documentation</h2> <ol> <li><a href="https://perldoc.perl.org/perlsyn">perlsyn</a> </ol> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/06/iterate-over-multiple-elements-at-the-same-time/" rel="bookmark"><time class="entry-date published" datetime="2024-06-15T18:56:16+00:00">June 15, 2024</time><time class="updated" datetime="2024-07-22T20:11:37+00:00">July 22, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-36/" rel="category tag">5.36</a>, <a href="https://www.effectiveperlprogramming.com/category/perl/5-38/" rel="category tag">5.38</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2716 --> <article id="post-2789" class="post-2789 post type-post status-publish format-standard hentry category-5-40 category-new-features"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/05/perl-v5-40-new-features/" rel="bookmark">Perl v5.40 New Features</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> These items are in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.</p> <p><br clear="all"/></p> <ul> <li><code>builtin</code> adds <code>nan</code> and <code>inf</code></li> <li><code>-M</code> command-line switch can now be followed by whitespace</li> <li>importing from an unloaded package name now warns</li> <li>lexical subroutines get some fixes</li> <li>The logical-xor operator <code>^^</code> joins <code>&&</code> and <code>||</code>.</li> <li><code>finally</code> blocks</li> <li>improved uninitialized value warnings</li> </ul> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/05/perl-v5-40-new-features/" rel="bookmark"><time class="entry-date published" datetime="2024-05-22T20:08:34+00:00">May 22, 2024</time><time class="updated" datetime="2024-07-22T20:09:44+00:00">July 22, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-40/" rel="category tag">5.40</a>, <a href="https://www.effectiveperlprogramming.com/category/perl/new-features/" rel="category tag">new features</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2789 --> <article id="post-2719" class="post-2719 post type-post status-publish format-standard hentry category-5-34 category-miscellany category-regular-expressions"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2024/03/insignificant-whitespace-in-brace-constructs/" rel="bookmark">Insignificant whitespace in brace constructs</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"/> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.</p> <p><br clear="all"/></p> <hr /> <p>Perl&#8217;s coterie of brace constructs become a bit more lenient in v5.34. These things appear in double-quotish constructs, such as <code>\N{CHARNAME}</code> to specify a character by name. And, patterns count as a double-quoted construct (unless you use <code>'</code> as the delimiter), so these new rules apply to brace constructs such as <code>\k{}</code> (for named backreferences) and the general quantifier, <code>{n,m}</code>.</p> <p> <a href="https://www.effectiveperlprogramming.com/2024/03/insignificant-whitespace-in-brace-constructs/#more-2719" class="more-link">Continue reading<span class="screen-reader-text"> &#8220;Insignificant whitespace in brace constructs&#8221;</span></a></p> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2024/03/insignificant-whitespace-in-brace-constructs/" rel="bookmark"><time class="entry-date published" datetime="2024-03-18T07:31:21+00:00">March 18, 2024</time><time class="updated" datetime="2024-07-22T20:30:26+00:00">July 22, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-34/" rel="category tag">5.34</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/regular-expressions/" rel="category tag">regular expressions</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2719 --> <article id="post-2738" class="post-2738 post type-post status-publish format-standard hentry category-5-34 category-miscellany"> <header class="entry-header"> <h2 class="entry-title"><a href="https://www.effectiveperlprogramming.com/2023/12/insignificant-leading-or-trailing-whitespace-in-brace-constructs/" rel="bookmark">Insignificant leading or trailing whitespace in brace constructs</a></h2> </header><!-- .entry-header --> <div class="entry-content"> <p><img src="/images/perl-new-features-small.jpg" align="left" style="margin-right: 1em"> This is a chapter in <a href="https://leanpub.com/perl_new_features">Perl New Features</a>, a book from <a href="https://perlschool.com">Perl School</a> that you can buy on <a href="https://leanpub.com/perl_new_features">LeanPub</a> or <a href="https://amzn.to/3QVsScf">Amazon</a>. Your support helps me to produce more content.</p> <p><br clear="all"/></p> <hr/> <p>Perl&#8217;s coterie of brace constructs become a bit more lenient in v5.34. These things appear in double-quotish constructs, such as <code>\N{CHARNAME}</code> to specify a character by name. And, patterns count as a double-quoted construct (unless you use <code>'</code> as the delimiter), so these new rules apply to brace constructs such as <code>\k{}</code> (for named backreferences) and the general quantifier, <code>{n,m}</code>.</p> <h2>Specifying characters</h2> <p>These constructs apply to double-quotish interpretation to specify a character by its codepoint or name:</p> <table> <tr> <th>Construct</th> <th>Description/th></p> <th>Item</th> </tr> <tr> <td><code>\N{CHARNAME}</code></td> <td>Character name</td> <td><a href="https://www.effectiveperlprogramming.com/2011/12/loose-match-unicode-character-names/">item</a></td> </tr> <tr> <td><code>\o{177}</code></td> <td>Octal code point</td> <td><a href="https://www.effectiveperlprogramming.com/2010/10/specify-any-character-by-its-octal-ordinal-value/">item</a></td> </tr> <tr> <td><code>\x{ABCD}</code></td> <td>Hex code point</td> <td></td> </tr> <tr> </table> <p>There are already loose names for <code>\N{}</code> that ignores whitespace (<a href="https://www.effectiveperlprogramming.com/2011/12/loose-match-unicode-character-names/">item</a>), but this feature is a bit different. It ignores horizontal whitespace around a value (but not inside a value):</p> <pre class="brush:perl"> use v5.10; use open qw(:std :utf8); say <<~"HERE"; Cat face: \N{ BLACK SPADE SUIT } Octal: \o{ 23140 } Hex: \x{ 2660 } HERE </pre> <p>This outputs the character we expect:</p> <pre class="brush:plain"> $ perl5.34.0 whitespace.pl Spade suit: ♠ Octal: ♠ Hex: ♠ </pre> <p>If you add space within the value, you don't get the character you want (the <code>\N{}</code> will actually fail):</p> <pre class="brush:perl"> use v5.34; use open qw(:std :utf8); say <<~"HERE"; Octal: \o{ 231 40 } Hex: \x{ 26 60 } HERE </pre> <p>This discards the cruft once it encounters non-digit characters (just like Perl's string-to-number conversions). This is effectively:</p> <pre class="brush:perl"> use v5.34; use open qw(:std :utf8); say <<~"HERE"; Octal: \o{ 231 } Hex: \x{ 26 } HERE </pre> <p>It's even worse. You can extra nonsense after the code number and v5.34 will ignore it. Although these have illegal digits (along with the internal space), they still work:</p> <pre class="brush:perl"> use v5.34; use open qw(:std :utf8); use warnings; say <<~"HERE"; Octal: \o{ 231 abc } Hex: \x{ 26 xyz } HERE </pre> <p>With trailing tabs or spaces, <a href="https://perldoc.perl.org/warnings">warnings</a> says that it ignores the cruft and uses what it received so far:</p> <pre class="brush:plain"> Non-octal character ' ' terminates \o early. Resolved as "\o{231}" at ... </pre> <p>With leading tabs or spaces, earlier Perls give up right away and uses the null character. The warning from v5.32 is this:</p> <pre class="brush:plain"> Non-octal character ' ' terminates \o early. Resolved as "\o{000}" at... </pre> <p>Finally, the whitespace can't be vertical space or other double-quote escapes (it's just literal tabs or spaces). These don't work:</p> <pre class="brush:perl"> \o{\t231} \o{ 231 } </pre> <p>In regular expressions, this fails before Perl interprets the pattern, where the <code>/x</code> would be able to handle the vertical whitespace. This would match a null byte because the string-to-number parsing stops at the first newline, returning <code>\000</code>:</p> <pre class="brush:perl"> m/\o{ 231 }/x; </pre> <h2>In regular expressions</h2> <p>And these constructs apply to regular expression features, and you don't need the <code>/x</code> flag to get this new, insignificant whitespace:</p> <table> <tr> <th>Construct </th> <th> Description </th> <th> Chapter </th> </tr> <tr> <td> <code>\b{TYPE}</code> </td> <td> Word boundary </td> <td> <a href="https://www.effectiveperlprogramming.com/2016/06/perl-v5-22-adds-fancy-unicode-word-boundaries/">Item</a> </td> </tr> <tr> <td> <code>\g{N}</code> </td> <td> Numbered backreference</td> <td> Item 31 (book) </td> </tr> <tr> <td> <code>\g{NAME}</code> </td> <td> Named backreference </td> <td> Item 31 (book) </td> </tr> <tr> <td> <code>\k{NAME}</code> </td> <td> Named backreference </td> <td> Item 31 (book) </td> </tr> <tr> <td> <code>\p{PROPNAME}</code> </td> <td> Unicode property name </td> <td> </td> </tr> <tr> <td> <code>\P{PROPNAME}</code> </td> <td> Unicode property name </td> <td> </td> </tr> <tr> <td> <code>\x{ABCD}</code> </td> <td> Hex code point </td> <td> </td> </tr> <tr> <td> <code>{n,m}</code> </td> <td> general quantifier </td> <td> </td> </tr> <tr> <td> </table> <p>The rules for these are similar to the same as those from the previous section. Perl ignores the tabs or spaces at the beginning<br /> or the end, but not in the middle (aside from around the <code>,</code> in <code>{n,m}</code>). For example, these all work:</p> <pre class="brush:perl"> use v5.10; use open qw(:std :utf8); use warnings; $_ = 'aa'; my @patterns = ( qr/(.)\g{ -1 }/, qr/(?<first>.)\g{ first }/, qr/(?<first>.)\k{ first }/, qr/\b{ sb }(.)/, qr/(\o{ 141 })\g{ -1 }/, qr/(\p{Letter})\g{ -1 }/, qr/(.)\g{ -1 }/, qr/(\x{ 61 })\g{ -1 }/, ); foreach my $pattern ( @patterns ) { say /$pattern/ }; </pre> </div><!-- .entry-content --> <footer class="entry-footer"> <span class="byline"><span class="author vcard"><img alt='' src='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=49&#038;d=mm&#038;r=g' srcset='https://secure.gravatar.com/avatar/edd8638efe875601bfe394a8aea5b16d?s=98&#038;d=mm&#038;r=g 2x' class='avatar avatar-49 photo' height='49' width='49' loading='lazy'/><span class="screen-reader-text">Author </span> <a class="url fn n" href="https://www.effectiveperlprogramming.com/author/bdfoy/">brian d foy</a></span></span><span class="posted-on"><span class="screen-reader-text">Posted on </span><a href="https://www.effectiveperlprogramming.com/2023/12/insignificant-leading-or-trailing-whitespace-in-brace-constructs/" rel="bookmark"><time class="entry-date published" datetime="2023-12-04T15:02:17+00:00">December 4, 2023</time><time class="updated" datetime="2024-04-15T00:11:07+00:00">April 15, 2024</time></a></span><span class="cat-links"><span class="screen-reader-text">Categories </span><a href="https://www.effectiveperlprogramming.com/category/perl/5-34/" rel="category tag">5.34</a>, <a href="https://www.effectiveperlprogramming.com/category/book/chapters/miscellany/" rel="category tag">miscellany</a></span> </footer><!-- .entry-footer --> </article><!-- #post-2738 --> <nav class="navigation pagination" aria-label="Posts"> <h2 class="screen-reader-text">Posts navigation</h2> <div class="nav-links"><span aria-current="page" class="page-numbers current"><span class="meta-nav screen-reader-text">Page </span>1</span> <a class="page-numbers" href="https://www.effectiveperlprogramming.com/page/2/"><span class="meta-nav screen-reader-text">Page </span>2</a> <span class="page-numbers dots">&hellip;</span> <a class="page-numbers" href="https://www.effectiveperlprogramming.com/page/24/"><span class="meta-nav screen-reader-text">Page </span>24</a> <a class="next page-numbers" href="https://www.effectiveperlprogramming.com/page/2/">Next page</a></div> </nav> </main><!-- .site-main --> </div><!-- .content-area --> <aside id="secondary" class="sidebar widget-area"> <section id="text-5" class="widget widget_text"> <div class="textwidget"><div id="book_picture" align="center"> <a href="https://amzn.to/2QtvIa2"><img src="/images/epp_second_edition.png" vspace="15px" border="0" alt="Effective Programming Perl book cover"/></a> </div> <br/> <div id="donate" align="center"> <script async type="text/javascript" id='fbnufur'>(function(i){var f,s=document.getElementById(i);f=document.createElement('iframe');f.src='//button.flattr.com/view/?uid=briandfoy&button=compact&url='+encodeURIComponent(document.URL);f.title='Flattr';f.height=20;f.width=110;f.style.borderWidth=0;s.parentNode.insertBefore(f,s);})('fbnufur');</script> <br/> <form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="hosted_button_id" value="11077925" /> <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" /> <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1" /> </form> </div></div> </section> <section id="recent-posts-3" class="widget widget_recent_entries"> <h2 class="widget-title">Latest Items</h2><nav aria-label="Latest Items"> <ul> <li> <a href="https://www.effectiveperlprogramming.com/2024/11/perl-v5-36-new-features/">Perl v5.36 new features</a> </li> <li> <a href="https://www.effectiveperlprogramming.com/2024/11/goodbye-fake-multidimensional-data-structures/">Goodbye fake multidimensional data structures</a> </li> <li> <a href="https://www.effectiveperlprogramming.com/2024/10/switch-removed-from-the-v5-36-feature-bundle/">switch removed from the v5.36 feature bundle</a> </li> <li> <a href="https://www.effectiveperlprogramming.com/2024/09/know-if-something-is-a-boolean/">Know if something is a boolean</a> </li> </ul> </nav></section><section id="categories-3" class="widget widget_categories"><h2 class="widget-title">Topics</h2><form action="https://www.effectiveperlprogramming.com" method="get"><label class="screen-reader-text" for="cat">Topics</label><select name='cat' id='cat' class='postform' > <option value='-1'>Select Category</option> <option class="level-0" value="3">administrative note&nbsp;&nbsp;(26)</option> <option class="level-1" value="54">&nbsp;&nbsp;&nbsp;midweek bonus item&nbsp;&nbsp;(7)</option> <option class="level-1" value="64">&nbsp;&nbsp;&nbsp;promotion&nbsp;&nbsp;(1)</option> <option class="level-1" value="4">&nbsp;&nbsp;&nbsp;publishing&nbsp;&nbsp;(15)</option> <option class="level-2" value="30">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eBook&nbsp;&nbsp;(7)</option> <option class="level-3" value="47">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ePub&nbsp;&nbsp;(2)</option> <option class="level-3" value="48">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iPad&nbsp;&nbsp;(3)</option> <option class="level-3" value="45">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Kindle&nbsp;&nbsp;(4)</option> <option class="level-3" value="46">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PDF&nbsp;&nbsp;(1)</option> <option class="level-3" value="52">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Safari Books Online&nbsp;&nbsp;(2)</option> <option class="level-2" value="29">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;translations&nbsp;&nbsp;(2)</option> <option class="level-1" value="39">&nbsp;&nbsp;&nbsp;reader feedback&nbsp;&nbsp;(1)</option> <option class="level-0" value="10">book&nbsp;&nbsp;(191)</option> <option class="level-1" value="9">&nbsp;&nbsp;&nbsp;chapters&nbsp;&nbsp;(163)</option> <option class="level-2" value="55">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpan&nbsp;&nbsp;(3)</option> <option class="level-2" value="23">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;databases&nbsp;&nbsp;(2)</option> <option class="level-2" value="19">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;distributions&nbsp;&nbsp;(4)</option> <option class="level-2" value="12">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;files &amp; filehandles&nbsp;&nbsp;(6)</option> <option class="level-2" value="51">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Idiomatic Perl&nbsp;&nbsp;(5)</option> <option class="level-2" value="13">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;miscellany&nbsp;&nbsp;(37)</option> <option class="level-2" value="31">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;references&nbsp;&nbsp;(8)</option> <option class="level-2" value="20">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;regular expressions&nbsp;&nbsp;(39)</option> <option class="level-2" value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subroutines&nbsp;&nbsp;(13)</option> <option class="level-2" value="57">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testing&nbsp;&nbsp;(6)</option> <option class="level-2" value="11">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The Basics of Perl&nbsp;&nbsp;(26)</option> <option class="level-2" value="15">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unicode&nbsp;&nbsp;(23)</option> <option class="level-2" value="67">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;warnings&nbsp;&nbsp;(4)</option> <option class="level-1" value="17">&nbsp;&nbsp;&nbsp;new chapters&nbsp;&nbsp;(38)</option> <option class="level-2" value="61">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;&nbsp;(2)</option> <option class="level-2" value="26">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debugging&nbsp;&nbsp;(8)</option> <option class="level-2" value="63">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;documentation&nbsp;&nbsp;(1)</option> <option class="level-2" value="22">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;external interactions&nbsp;&nbsp;(1)</option> <option class="level-2" value="40">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formats&nbsp;&nbsp;(1)</option> <option class="level-2" value="24">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;html&nbsp;&nbsp;(1)</option> <option class="level-2" value="33">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;networking&nbsp;&nbsp;(1)</option> <option class="level-2" value="44">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numbers&nbsp;&nbsp;(3)</option> <option class="level-2" value="53">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object-oriented programming&nbsp;&nbsp;(11)</option> <option class="level-2" value="60">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pack&nbsp;&nbsp;(1)</option> <option class="level-2" value="65">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PAUSE&nbsp;&nbsp;(1)</option> <option class="level-2" value="25">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;performance&nbsp;&nbsp;(5)</option> <option class="level-2" value="38">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Programming tips&nbsp;&nbsp;(3)</option> <option class="level-2" value="85">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;security&nbsp;&nbsp;(1)</option> <option class="level-2" value="18">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xml&nbsp;&nbsp;(2)</option> <option class="level-1" value="32">&nbsp;&nbsp;&nbsp;table of contents&nbsp;&nbsp;(1)</option> <option class="level-0" value="49">conferences&nbsp;&nbsp;(2)</option> <option class="level-0" value="6">event announcement&nbsp;&nbsp;(5)</option> <option class="level-1" value="37">&nbsp;&nbsp;&nbsp;book signing&nbsp;&nbsp;(1)</option> <option class="level-1" value="7">&nbsp;&nbsp;&nbsp;classroom training&nbsp;&nbsp;(4)</option> <option class="level-1" value="34">&nbsp;&nbsp;&nbsp;yapc&nbsp;&nbsp;(2)</option> <option class="level-0" value="50">free stuff&nbsp;&nbsp;(1)</option> <option class="level-0" value="14">git&nbsp;&nbsp;(3)</option> <option class="level-0" value="59">item&nbsp;&nbsp;(104)</option> <option class="level-0" value="5">perl&nbsp;&nbsp;(124)</option> <option class="level-1" value="28">&nbsp;&nbsp;&nbsp;5.10&nbsp;&nbsp;(12)</option> <option class="level-1" value="27">&nbsp;&nbsp;&nbsp;5.12&nbsp;&nbsp;(15)</option> <option class="level-1" value="41">&nbsp;&nbsp;&nbsp;5.14&nbsp;&nbsp;(13)</option> <option class="level-1" value="58">&nbsp;&nbsp;&nbsp;5.16&nbsp;&nbsp;(7)</option> <option class="level-1" value="66">&nbsp;&nbsp;&nbsp;5.18&nbsp;&nbsp;(7)</option> <option class="level-1" value="68">&nbsp;&nbsp;&nbsp;5.20&nbsp;&nbsp;(11)</option> <option class="level-1" value="69">&nbsp;&nbsp;&nbsp;5.22&nbsp;&nbsp;(6)</option> <option class="level-1" value="70">&nbsp;&nbsp;&nbsp;5.24&nbsp;&nbsp;(4)</option> <option class="level-1" value="73">&nbsp;&nbsp;&nbsp;5.26&nbsp;&nbsp;(13)</option> <option class="level-1" value="74">&nbsp;&nbsp;&nbsp;5.28&nbsp;&nbsp;(10)</option> <option class="level-1" value="89">&nbsp;&nbsp;&nbsp;5.30&nbsp;&nbsp;(6)</option> <option class="level-1" value="91">&nbsp;&nbsp;&nbsp;5.32&nbsp;&nbsp;(6)</option> <option class="level-1" value="96">&nbsp;&nbsp;&nbsp;5.34&nbsp;&nbsp;(5)</option> <option class="level-1" value="99">&nbsp;&nbsp;&nbsp;5.36&nbsp;&nbsp;(8)</option> <option class="level-1" value="100">&nbsp;&nbsp;&nbsp;5.38&nbsp;&nbsp;(2)</option> <option class="level-1" value="101">&nbsp;&nbsp;&nbsp;5.40&nbsp;&nbsp;(1)</option> <option class="level-1" value="43">&nbsp;&nbsp;&nbsp;5.8&nbsp;&nbsp;(1)</option> <option class="level-1" value="79">&nbsp;&nbsp;&nbsp;broken feature&nbsp;&nbsp;(5)</option> <option class="level-1" value="86">&nbsp;&nbsp;&nbsp;experimental&nbsp;&nbsp;(2)</option> <option class="level-1" value="92">&nbsp;&nbsp;&nbsp;fixed feature&nbsp;&nbsp;(2)</option> <option class="level-1" value="42">&nbsp;&nbsp;&nbsp;new features&nbsp;&nbsp;(19)</option> <option class="level-1" value="71">&nbsp;&nbsp;&nbsp;removed features&nbsp;&nbsp;(7)</option> <option class="level-0" value="16">presentations&nbsp;&nbsp;(2)</option> <option class="level-0" value="35">talks&nbsp;&nbsp;(2)</option> <option class="level-1" value="36">&nbsp;&nbsp;&nbsp;slides available&nbsp;&nbsp;(2)</option> </select> </form> <script> /* <![CDATA[ */ (function() { var dropdown = document.getElementById( "cat" ); function onCatChange() { if ( dropdown.options[ dropdown.selectedIndex ].value > 0 ) { dropdown.parentNode.submit(); } } dropdown.onchange = onCatChange; })(); /* ]]> */ </script> </section><section id="archives-3" class="widget widget_archive"><h2 class="widget-title">Archives</h2> <label class="screen-reader-text" for="archives-dropdown-3">Archives</label> <select id="archives-dropdown-3" name="archive-dropdown"> <option value="">Select Month</option> <option value='https://www.effectiveperlprogramming.com/2024/11/'> November 2024 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2024/10/'> October 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/09/'> September 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/08/'> August 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/07/'> July 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/06/'> June 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/05/'> May 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2024/03/'> March 2024 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2023/12/'> December 2023 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2023/11/'> November 2023 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2023/07/'> July 2023 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2021/03/'> March 2021 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2020/07/'> July 2020 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2020/06/'> June 2020 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2020/03/'> March 2020 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2020/01/'> January 2020 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2019/09/'> September 2019 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2019/07/'> July 2019 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2019/03/'> March 2019 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2019/02/'> February 2019 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2018/12/'> December 2018 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2018/10/'> October 2018 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2018/09/'> September 2018 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2018/08/'> August 2018 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2018/04/'> April 2018 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2018/01/'> January 2018 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2017/12/'> December 2017 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2017/09/'> September 2017 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2017/08/'> August 2017 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2017/04/'> April 2017 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2017/01/'> January 2017 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2016/12/'> December 2016 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2016/06/'> June 2016 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2016/04/'> April 2016 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2016/03/'> March 2016 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2016/01/'> January 2016 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/11/'> November 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/10/'> October 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/08/'> August 2015 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2015/07/'> July 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/06/'> June 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/05/'> May 2015 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2015/04/'> April 2015 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2015/02/'> February 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2015/01/'> January 2015 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2014/12/'> December 2014 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2014/11/'> November 2014 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2014/10/'> October 2014 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2014/09/'> September 2014 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2014/08/'> August 2014 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2014/07/'> July 2014 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2014/06/'> June 2014 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2013/08/'> August 2013 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2013/06/'> June 2013 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2013/05/'> May 2013 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2012/10/'> October 2012 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2012/08/'> August 2012 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2012/07/'> July 2012 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2012/04/'> April 2012 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2012/03/'> March 2012 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2012/02/'> February 2012 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2012/01/'> January 2012 &nbsp;(2)</option> <option value='https://www.effectiveperlprogramming.com/2011/12/'> December 2011 &nbsp;(4)</option> <option value='https://www.effectiveperlprogramming.com/2011/11/'> November 2011 &nbsp;(3)</option> <option value='https://www.effectiveperlprogramming.com/2011/10/'> October 2011 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2011/09/'> September 2011 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2011/08/'> August 2011 &nbsp;(4)</option> <option value='https://www.effectiveperlprogramming.com/2011/07/'> July 2011 &nbsp;(6)</option> <option value='https://www.effectiveperlprogramming.com/2011/06/'> June 2011 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2011/05/'> May 2011 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2011/04/'> April 2011 &nbsp;(4)</option> <option value='https://www.effectiveperlprogramming.com/2011/03/'> March 2011 &nbsp;(4)</option> <option value='https://www.effectiveperlprogramming.com/2011/02/'> February 2011 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2011/01/'> January 2011 &nbsp;(6)</option> <option value='https://www.effectiveperlprogramming.com/2010/12/'> December 2010 &nbsp;(8)</option> <option value='https://www.effectiveperlprogramming.com/2010/11/'> November 2010 &nbsp;(7)</option> <option value='https://www.effectiveperlprogramming.com/2010/10/'> October 2010 &nbsp;(8)</option> <option value='https://www.effectiveperlprogramming.com/2010/09/'> September 2010 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2010/08/'> August 2010 &nbsp;(7)</option> <option value='https://www.effectiveperlprogramming.com/2010/07/'> July 2010 &nbsp;(10)</option> <option value='https://www.effectiveperlprogramming.com/2010/06/'> June 2010 &nbsp;(5)</option> <option value='https://www.effectiveperlprogramming.com/2010/05/'> May 2010 &nbsp;(10)</option> <option value='https://www.effectiveperlprogramming.com/2010/04/'> April 2010 &nbsp;(8)</option> <option value='https://www.effectiveperlprogramming.com/2010/03/'> March 2010 &nbsp;(4)</option> <option value='https://www.effectiveperlprogramming.com/2010/02/'> February 2010 &nbsp;(6)</option> <option value='https://www.effectiveperlprogramming.com/2010/01/'> January 2010 &nbsp;(7)</option> <option value='https://www.effectiveperlprogramming.com/2009/12/'> December 2009 &nbsp;(1)</option> <option value='https://www.effectiveperlprogramming.com/2008/01/'> January 2008 &nbsp;(1)</option> </select> <script> /* <![CDATA[ */ (function() { var dropdown = document.getElementById( "archives-dropdown-3" ); function onSelectChange() { if ( dropdown.options[ dropdown.selectedIndex ].value !== '' ) { document.location.href = this.options[ this.selectedIndex ].value; } } dropdown.onchange = onSelectChange; })(); /* ]]> */ </script> </section><section id="text-6" class="widget widget_text"><h2 class="widget-title">External Links</h2> <div class="textwidget"><ul> <li><a href="https://www.amazon.com/gp/product/0321496949/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321496949&amp;linkCode=as2&amp;tag=hashbang09-20&amp;linkId=JLZLK3MHRS2VVEJW">Amazon.com</a></li> <li><a href="https://www.pearsonhighered.com/educator/product/Effective-Perl-Programming-Ways-to-Write-Better-More-Idiomatic-Perl-2E/9780321496942.page">publisher catalog page</a></li> <li><a href="https://www.informit.com/store/product.aspx?isbn=0321496949">InformIT page (book and PDF)</a></li> <li><a href="https://my.safaribooksonline.com/9780321718303">Safari Books Online</a></li> <li><a href="https://www.ebooks.com/ebooks/book_display.asp?IID=515079">eBooks (PDF and ePub)</a></li> </ul></div> </section><section id="text-3" class="widget widget_text"> <div class="textwidget"><div align="center"> <script async type="text/javascript"> var amzn_wdgt={widget:'Carousel'}; amzn_wdgt.tag='hashbang09-20'; amzn_wdgt.widgetType='ASINList'; amzn_wdgt.title='Our Perl Books'; amzn_wdgt.width='250'; amzn_wdgt.ASIN='1449303587,1449393098,144939311X,0321496949,059600492,0596004923'; amzn_wdgt.width='200'; amzn_wdgt.height='600'; </script> <script async type="text/javascript" src='https://wms.assoc-amazon.com/20070822/US/js/swfobject_1_5.js'> </script> </div></div> </section> </aside><!-- .sidebar .widget-area --> </div><!-- .site-content --> <footer id="colophon" class="site-footer"> <nav class="main-navigation" aria-label="Footer Primary Menu"> <div class="menu-menu-container"><ul id="menu-menu-1" class="primary-menu"><li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2706"><a href="https://www.effectiveperlprogramming.com/toc/">TOC</a></li> <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2707"><a href="https://www.effectiveperlprogramming.com/errata/">Errata</a></li> <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-2708"><a href="https://www.effectiveperlprogramming.com/about/">About</a></li> </ul></div> </nav><!-- .main-navigation --> <div class="site-info"> <span class="site-title"><a href="https://www.effectiveperlprogramming.com/" rel="home">The Effective Perler</a></span> <a href="https://wordpress.org/" class="imprint"> Proudly powered by WordPress </a> </div><!-- .site-info --> </footer><!-- .site-footer --> </div><!-- .site-inner --> </div><!-- .site --> <script src='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/js/skip-link-focus-fix.js?ver=20170530' id='twentysixteen-skip-link-focus-fix-js'></script> <script id='twentysixteen-script-js-extra'> var screenReaderText = {"expand":"expand child menu","collapse":"collapse child menu"}; </script> <script src='https://www.effectiveperlprogramming.com/wp-content/themes/twentysixteen/js/functions.js?ver=20181217' id='twentysixteen-script-js'></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10