CINXE.COM

Switch::Back - given/when for a post-given/when Perl - metacpan.org

<!DOCTYPE html> <html lang="en-US"> <head> <title>Switch::Back - given/when for a post-given/when Perl - metacpan.org</title> <link rel="preload" as="fetch" href="/account/login_status" crossorigin="anonymous" /> <link href="/assets/style-XFEQ536G.css" rel="stylesheet" type="text/css"> <script src="/assets/main-WXBSEDQJ.js" type="module"></script> <link rel="alternate" type="application/rss+xml" title="Recent CPAN Uploads of Switch-Back - MetaCPAN" href="/dist/Switch-Back/releases.rss" /> <link rel="canonical" href="https://metacpan.org/pod/Switch::Back" /> <meta name="description" content="given/when for a post-given/when Perl" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5"> <link rel="shortcut icon" href="/static/icons/favicon.ico"> <link rel="apple-touch-icon" sizes="152x152" href="/static/icons/apple-touch-icon.png"> <link rel="search" href="/static/opensearch.xml" type="application/opensearchdescription+xml" title="MetaCPAN"> <script async src="https://perl-ads.perlhacks.com/perl-ads.js"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-E82Q2V8LVD"></script> <meta property="og:site_name" content="MetaCPAN" /> <meta name="twitter:site" content="@metacpan" /> <meta property="og:type" content="article" /> <meta name="twitter:card" content="summary" /> <meta property="og:url" content="https://metacpan.org/pod/Switch::Back" /> <meta property="og:title" content="Switch::Back" /> <meta property="og:description" content="given/when for a post-given/when Perl" /> <meta property="og:image" content="https://metacpan.org/static/images/dots.png" /> </head> <body> <nav class="navbar navbar-default" role="navigation"> <div class="header-logo-large hidden-xs"> <a href="/" tabindex="0"> <svg class="logo" aria-label="MetaCPAN"> <use class="logo" href="/static/images/metacpan-logo.svg#logo" /> </svg> </a> </div> <div class="header-logo-icon visible-xs"> <a href="/"> <svg class="logo" aria-label="MetaCPAN"> <use class="logo" href="/static/images/metacpan-logo.svg#dots" /> </svg> </a> </div> <ul class="nav navbar-nav menu-items hidden-xs hidden-sm"> <li><a href="/about">About</a></li> <li><a href="/about/sponsors">Sponsor</a></li> <li><a href="https://grep.metacpan.org/">grep::cpan</a></li> <li><a href="/recent">Recent</a></li> <li><a href="/about/faq">FAQ</a></li> <li><a href="/tools">Tools</a></li> <li><a href="https://fastapi.metacpan.org/">API</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <button type="button" class="searchbar-btn visible-xs visible-sm"> <i class="fa fa-search button-fa-icon"></i> </button> <form action="/search" class="searchbar-form visible-md visible-lg search-form form-horizontal"> <input type="hidden" name="size" id="metacpan_search-size" value="20"> <div class="form-group"> <div class="search-group"> <i class="fa fa-search"></i> <input type="text" name="q" placeholder="Search the CPAN" size="41" autocorrect="off" autocapitalize="off" spellcheck="false" id="metacpan_search-input" class="form-control" value=""> </div> </div> </form> <li class="icon-slidepanel visible-xs visible-sm"> <button data-toggle="slidepanel" data-target=".slidepanel"> <span class="button-fa-icon"> <i class="fa fa-bars slidepanel-open"></i> <i class="fa fa-times slidepanel-close"></i> </span> </button> </li> <li class="dropdown login-dropdown show-logged-in"> <button type="button" class="dropdown-toggle" data-toggle="dropdown"> <i class="fa fa-user button-fa-icon logged-in-icon" aria-hidden="true"></i> <i class="fas fa-chevron-down"></i> </button> <ul class="dropdown-menu"> <li><a href="/account/identities">Identities</a></li> <li><a href="/account/profile">Profile</a></li> <li><a href="/account/favorite/list">Favorites</a></li> <li> <a href="#" type="button" class="logout-button"> Logout </a> </li> </ul> </li> <li class="dropdown login-dropdown show-logged-out"> <button type="button" class="dropdown-toggle" data-toggle="dropdown"> <i class="fa fa-user button-fa-icon avatar-placeholder" aria-hidden="true"></i> <i class="fas fa-chevron-down"></i> </button> <ul class="dropdown-menu"> <li> <a href="/login/github"> <i class="fab fa-github fa-fw"></i> GitHub </a> </li> <li> <a href="/login/twitter"> <i class="fab fa-twitter fa-fw"></i> Twitter </a> </li> <li> <a href="/login/google"> <i class="fab fa-google fa-fw"></i> Google </a> </li> </ul> </li> <li class="dropdown login-dropdown hide-logged-in hide-logged-out"> <button> <i class="fa fa-user button-fa-icon" aria-hidden="true"></i> </button> </li> </ul> </nav> <div class="page-content "> <div id="perl-ad-target" class="top-notify-banner perl-ad-target"> </div> <nav class="sidebar"> <div class="slidepanel"> <ul class="nav-list "> <li class="nav-header no-margin-top"> <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The date that this version of Switch-Back was released."> <span class="relatize">09 Feb 2025 11:30:59 UTC</span> </div> </li> <li> Distribution: <a href="/dist/Switch-Back">Switch-Back</a> </li> <li> Module version: 0.000005 </li> <li> <a data-keyboard-shortcut="g s" href="/dist/Switch-Back/source/lib/Switch/Back.pm">Source</a> (<a href="/dist/Switch-Back/source/lib/Switch/Back.pm?raw=1">raw</a>) </li> <li> <a data-keyboard-shortcut="g b" href="/dist/Switch-Back/source/lib/Switch">Browse</a> (<a href="/dist/Switch-Back/source/lib/Switch?raw=1">raw</a>) </li> <li> <a data-keyboard-shortcut="g c" href="/dist/Switch-Back/changes">Changes</a> </li> <li> <a class="nopopup" href="/dist/Switch-Back/contribute">How to Contribute</a> </li> <li> <a rel="noopener nofollow" data-keyboard-shortcut="g i" href="https://rt.cpan.org/Public/Dist/Display.html?Name=Switch-Back">Issues</a> (0) </li> <li> <a rel="noopener nofollow" href="http://matrix.cpantesters.org/?dist=Switch-Back+0.000005" title="Matrix">Testers</a> </li> <li> <a rel="noopener nofollow" href="http://cpants.cpanauthors.org/release/DCONWAY/Switch-Back-0.000005">Kwalitee</a> </li> <li> <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The # people with an indexing permission on Switch-Back who have released something to CPAN in the last 2 years (i.e. the # people likely able to release critical fixes in a timely manner)"> Bus factor: 1 </div> </li> <li> License: artistic_2 </li> <li> Perl: v5.36.0 </li> <li class="nav-header">Activity</li> <li> <div class="activity-graph"> <img src="/dist/Switch-Back/activity.svg?res=month" /> <div class="comment">24 month</div> </div> </li> <li class="nav-header">Tools</li> <li> <a itemprop="downloadUrl" href="https://cpan.metacpan.org/authors/id/D/DC/DCONWAY/Switch-Back-0.000005.tar.gz"> Download (<span itemprop="fileSize">26.78KB</span>)</a> </li> <li> <a href="https://explorer.metacpan.org/?url=%2Fmodule%2FDCONWAY%2FSwitch-Back-0.000005%2Flib%2FSwitch%2FBack.pm"> MetaCPAN Explorer </a> </li> <li> <a href="/dist/Switch-Back/permissions"> Permissions </a> </li> <li> <a href="/dist/Switch-Back/releases.rss"> Subscribe to distribution </a> </li> <li> <button class="btn btn-link" data-toggle="modal" data-target="#metacpan_install-instructions-dialog"> Install Instructions </button> </li> <li> <form action="/search"> <input type="hidden" name="q" value="dist:Switch-Back"> <input type="search" name="q" placeholder="Search distribution" class="form-control tool-bar-form"> <input type="submit" style="display: none"> </form> </li> <li> <form action="https://grep.metacpan.org/search"> <input type="hidden" name="qd" value="Switch-Back"> <input type="hidden" name="source" value="metacpan"> <input type="search" name="q" placeholder="grep distribution" class="form-control tool-bar-form"> <input type="submit" style="display: none"> </form> </li> <li class="version-jump"> <select class="select-navigator form-control tool-bar-form"> <option disabled selected>Jump to version</option> <option disabled value="/release/DCONWAY/Switch-Back-0.000005/view/lib/Switch/Back.pm" >0.000005 (DCONWAY on 2025-02-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000004/view/lib/Switch/Back.pm" >0.000004 (DCONWAY on 2025-02-08)</option> <option value="/release/DCONWAY/Switch-Back-0.000003/view/lib/Switch/Back.pm" >0.000003 (DCONWAY on 2025-01-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000002/view/lib/Switch/Back.pm" >0.000002 (DCONWAY on 2024-06-26)</option> </select> </li> <li class="version-diff"> <select class="select-navigator form-control tool-bar-form"> <option disabled selected>Diff with version</option> <option disabled value="/release/DCONWAY/Switch-Back-0.000005/diff/DCONWAY/Switch-Back-0.000005/lib/Switch/Back.pm" >0.000005 (DCONWAY on 2025-02-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000005/diff/DCONWAY/Switch-Back-0.000004/lib/Switch/Back.pm" >0.000004 (DCONWAY on 2025-02-08)</option> <option value="/release/DCONWAY/Switch-Back-0.000005/diff/DCONWAY/Switch-Back-0.000003/lib/Switch/Back.pm" >0.000003 (DCONWAY on 2025-01-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000005/diff/DCONWAY/Switch-Back-0.000002/lib/Switch/Back.pm" >0.000002 (DCONWAY on 2024-06-26)</option> </select> </li> <li> <ul class="dependencies"> <li class="nav-header">Dependencies</li> <li><a href="/pod/B::Deparse" title="B::Deparse" class="ellipsis">B::Deparse</a></li> <li><a href="/pod/Keyword::Simple" title="Keyword::Simple" class="ellipsis">Keyword::Simple</a></li> <li><a href="/pod/Multi::Dispatch" title="Multi::Dispatch" class="ellipsis">Multi::Dispatch</a></li> <li><a href="/pod/PPR" title="PPR" class="ellipsis">PPR</a></li> <li><a href="/pod/Test::More" title="Test::More" class="ellipsis">Test::More</a></li> <li><a href="/pod/Type::Tiny" title="Type::Tiny" class="ellipsis">Type::Tiny</a></li> <li><i class="ttip" title="dynamic_config enabled">and possibly others</i></li> <li> <hr> </li> <li> <a href="/module/Switch::Back/requires">Reverse dependencies</a> </li> <li> <a href="http://deps.cpantesters.org/?module=Switch%3A%3ABack">CPAN Testers List</a> </li> <li> <a href="https://cpandeps.grinnz.com/?dist=Switch-Back">Dependency graph</a> </li> </ul> </li> <li class="nav-header">Permalinks</li> <li> <a href="/release/DCONWAY/Switch-Back-0.000005/view/lib/Switch/Back.pm">This version</a> </li> <li> <a href="/pod/Switch::Back">Latest version</a> </li> <li> </li> <li> <div> <button class="contributors-show-button btn-link">and 1 contributors</button> <div id="metacpan_contributors" class="slide-out slide-out-hidden"> <div> <ul> <li class="contributor" data-contrib-email="DCONWAY@CPAN.org" > <img class="gravatar" width="20" height="20" src="https://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=identicon&amp;s=20" /> Damian Conway </li> </ul> </div> </div> </div> </li> </ul> </div> </nav> <div class="content-navigation"> <div class="breadcrumbs"> <span> <a data-keyboard-shortcut="g a" rel="author" href="/author/DCONWAY" class="author-name">Damian Conway</a> </span> <span>&nbsp;/&nbsp;</span> <div class="release dist-release status-latest maturity-released"> <span class="dropdown"><b class="caret"></b></span> <select class="select-navigator "> <option selected value="/release/DCONWAY/Switch-Back-0.000005/view/lib/Switch/Back.pm" >0.000005 (DCONWAY on 2025-02-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000004/view/lib/Switch/Back.pm" >0.000004 (DCONWAY on 2025-02-08)</option> <option value="/release/DCONWAY/Switch-Back-0.000003/view/lib/Switch/Back.pm" >0.000003 (DCONWAY on 2025-01-09)</option> <option value="/release/DCONWAY/Switch-Back-0.000002/view/lib/Switch/Back.pm" >0.000002 (DCONWAY on 2024-06-26)</option> </select> <a data-keyboard-shortcut="g d" class="release-name" href="/dist/Switch-Back">Switch-Back-0.000005</a> </div> <span class="river-gauge-gauge"> <svg width="24px" height="15px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g> <title> River stage one &#10; • 1 direct dependent &#10; • 1 total dependent </title> <rect x="0" y="0" width="4" height="15" fill="#7ea3f2" /> <rect x="5" y="0" width="4" height="15" fill="#e4e2e2" /> <rect x="10" y="0" width="4" height="15" fill="#e4e2e2" /> <rect x="15" y="0" width="4" height="15" fill="#e4e2e2" /> <rect x="20" y="0" width="4" height="15" fill="#e4e2e2" /> </g> </svg> </span> <div id="Switch-Back-fav" class="show-logged-in"> <form action="/account/favorite/add" style="display: inline" method="POST"> <input type="hidden" name="remove" value="0"> <input type="hidden" name="release" value="Switch-Back-0.000005"> <input type="hidden" name="author" value="DCONWAY"> <input type="hidden" name="distribution" value="Switch-Back"> <button type="submit" class="favorite"><span></span> ++</button> </form> </div> <div class="show-logged-out"> <button class="fav-not-logged-in favorite"><span></span> ++</button> </div> / <span>Switch::Back</span> </div> </div> <main class="content"> <nav class="toc"> <div class="toc-header"><strong>Contents</strong></div> <ul> <li><a href="#NAME">NAME</a></li> <li><a href="#VERSION">VERSION</a></li> <li><a href="#SYNOPSIS">SYNOPSIS</a></li> <li><a href="#DESCRIPTION">DESCRIPTION</a></li> <li><a href="#INTERFACE">INTERFACE</a> <ul> <li><a href="#Smartmatching-differences">Smartmatching differences</a> <ul> <li><a href="#1.-No-auto-enreferencing-of-arguments">1. No auto-enreferencing of arguments</a></li> <li><a href="#2.-No-overloading-of-~~">2. No overloading of ~~</a></li> </ul> </li> <li><a href="#Overloading-smartmatch()">Overloading smartmatch()</a></li> </ul> </li> <li><a href="#LIMITATIONS">LIMITATIONS</a> <ul> <li><a href="#Limitation-1.-You-can%27t-always-use-a-given-inside-a-do-block">Limitation 1. You can&#39;t always use a given inside a do block</a></li> <li><a href="#2.-Use-of-when-modifiers-outside-a-given">2. Use of when modifiers outside a given</a></li> <li><a href="#3.-Scoping-anomalies-of-when-modifiers">3. Scoping anomalies of when modifiers</a></li> </ul> </li> <li><a href="#DIAGNOSTICS">DIAGNOSTICS</a></li> <li><a href="#CONFIGURATION-AND-ENVIRONMENT">CONFIGURATION AND ENVIRONMENT</a></li> <li><a href="#DEPENDENCIES">DEPENDENCIES</a></li> <li><a href="#INCOMPATIBILITIES">INCOMPATIBILITIES</a></li> <li><a href="#BUGS">BUGS</a></li> <li><a href="#SEE-ALSO">SEE ALSO</a></li> <li><a href="#AUTHOR">AUTHOR</a></li> <li><a href="#LICENCE-AND-COPYRIGHT">LICENCE AND COPYRIGHT</a></li> <li><a href="#DISCLAIMER-OF-WARRANTY">DISCLAIMER OF WARRANTY</a></li> </ul></nav> <div class="pod anchors"> <h1 id="NAME">NAME</h1> <p>Switch::Back - <code>given</code>/<code>when</code> for a post-<code>given</code>/<code>when</code> Perl</p> <h1 id="VERSION">VERSION</h1> <p>This document describes Switch::Back version 0.000005</p> <h1 id="SYNOPSIS">SYNOPSIS</h1> <pre><code>use v5.42; # given/when were removed in this version of Perl use Switch::Back; # But this module brings them back given ($some_value) { when (1) { say 1; } when (&#39;a&#39;) { say &#39;a&#39;; continue; } break when [&#39;b&#39;..&#39;e&#39;]; default { say &quot;other: $_&quot; } }</code></pre> <h1 id="DESCRIPTION">DESCRIPTION</h1> <p>The <code>given</code>/<code>when</code> construct was added to Perl in v5.10, deprecated in Perl v5.38, and removed from the language in Perl v5.42.</p> <p>Code that uses the construct must therefore be rewritten if it is to be used with any Perl after v5.40.</p> <p>Or you can leave the <code>given</code> and <code>when</code> code in place and use this module to (partially) resurrect the former feature in more recent Perls.</p> <p>The module exports three keywords: <code>given</code>, <code>when</code>, and <code>default</code>, and two subroutines: <code>break</code> and <code>continue</code>, which collectively provide most of the previous behaviour provided by <code>use feature &#39;switch&#39;</code>.</p> <p>The module <i>doesn&#39;t</i> resurrect the smartmatch operator (<code>~~</code>), but does export a <code>smartmatch()</code> subroutine that implements a nearly complete subset of the operator&#39;s former behaviour.</p> <h1 id="INTERFACE">INTERFACE</h1> <p>The module has no options or configuration. You simply load the module:</p> <pre><code>use Switch::Back;</code></pre> <p>...and its exported keywords will then rewrite the rest of your source code <i>(safely, using the extensible keyword mechanism, <b>not</b> a source filter)</i> to translate any subsequent <code>given</code>, <code>when</code>, and <code>default</code> blocks into the equivalent post-Perl-v5.42 code. See <a href="#LIMITATIONS">&quot;LIMITATIONS&quot;</a> for an overview of just how backwards compatible (or not) this approach is.</p> <p>Loading the module also unconditionally exports two subroutines, <code>break()</code> and <code>continue()</code>, which provide the same explicit flow control as the former built-in <code>break()</code> and <code>continue()</code> functions.</p> <p>The module also unconditionally exports a multiply dispatched subroutine named <code>smartmatch()</code>, which takes two arguments and smartmatches them using the same logic as the former <code>~~</code> operator. See <a href="#Smartmatching-differences">&quot;Smartmatching differences&quot;</a> for a summary of the differences between <code>smartmatch()</code> and the former built-in <code>~~</code> operator. See <a href="#Overloading-smartmatch()">&quot;Overloading <code>smartmatch()</code>&quot;</a> for an explanation of how to add new matching behaviours to <code>smartmatch()</code> (now that <code>~~</code> is no longer overloadable).</p> <h2 id="Smartmatching-differences"><a id="Smartmatching"></a>Smartmatching differences</h2> <p>The <code>smartmatch()</code> subroutine provided by this module implements almost all of the behaviours of the <a href="https://perldoc.perl.org/5.40.0/perlop#Smartmatch-Operator">former <code>~~</code> operator</a>, with the exceptions listed below.</p> <p>Note, however, that despite these limitations on smartmatching, the <code>given</code> and <code>when</code> keywords implement almost the complete range of smartmatching behaviours of the former <code>given</code> and <code>when</code> constructs. Specifically these two keywords will still auto-enreference arrays, hashes, and slices that are passed to them, and <code>when</code> also implements the so-called <a href="https://perldoc.perl.org/5.40.0/perlsyn#Experimental-Details-on-given-and-when">&quot;smartsmartmatching&quot; behaviours on boolean expressions</a>.</p> <h3 id="1.-No-auto-enreferencing-of-arguments"><a id="1"></a><a id="No-auto-enreferencing-of-arguments"></a>1. No auto-enreferencing of arguments</h3> <p>The <code>smartmatch()</code> subroutine is a regular Perl subroutine so, unlike the <code>~~</code> operator, it cannot auto-enreference an array or hash or slice that is passed to it. That is:</p> <pre><code> %hash ~~ @array # Works (autoconverted to; \%hash ~~ \@array) smartmatch( %hash, @array) # Error (hash and array are flattened within arglist) smartmatch(\%hash, \@array) # Works (smartmatch() always expects two args)</code></pre> <h3 id="2.-No-overloading-of-~~"><a id="2"></a><a id="No-overloading-of"></a>2. No overloading of <code>~~</code></h3> <p>Because overloading of the <code>~~</code> operator was removed in Perl 5.42, the <code>smartmatch()</code> subroutine always dies if its right argument is an object. The former <code>~~</code> would first attempt to call the object&#39;s overloaded <code>~~</code>, only dying if no suitable overload was found. See <a href="#Overloading-smartmatch()">&quot;Overloading <code>smartmatch()</code>&quot;</a> for details on how to extend the behavior of <code>smartmatch()</code> so it can accept objects.</p> <h2 id="Overloading-smartmatch()"><a id="Overloading"></a><a id="Overloading-smartmatch"></a>Overloading <code>smartmatch()</code></h2> <p>Because the <code>smartmatch()</code> subroutine provided by this module is actually a <i>multisub</i>, implemented via the <a href="/pod/Multi::Dispatch">Multi::Dispatch</a> module, it can easily be extended to match between additional types of arguments.</p> <p>For example, if you want to be able to smartmatch against an <code>ID::Validator</code> object (by calling its <code>validate()</code> method), you would just write:</p> <pre><code>use Switch::Back; use Multi::Dispatch; # Define new smartmatching behaviour on ID::Validator objects... multi smartmatch ($value, ID::Validator $obj) { return $obj-&gt;validate( $value ); } # and thereafter... state $VALID_ID = ID::Validator-&gt;new(); given ($id) { when ($VALID_ID) { say &#39;valid ID&#39; } # Same as: if ($VALID_ID-&gt;validate($_)) {...} default { die &#39;invalid ID&#39; } }</code></pre> <p>More generally, if you wanted to allow any object to be passed as the right-hand argument to <code>smartmatch()</code>, provided the object has a stringification or numerification overloading, you could write:</p> <pre><code>use Multi::Dispatch; use Types::Standard &#39;:all&#39;; # Allow smartmatch() to accept RHS objects that can convert to numbers... multi smartmatch (Num $left, Overload[&#39;0+&#39;] $right) { return next::variant($left, 0+$right); } # Allow smartmatch() to accept RHS objects that can convert to strings... multi smartmatch (Str $left, Overload[q{&quot;&quot;}] $right) { return next::variant($left, &quot;$right&quot;); }</code></pre> <p>You can also change the existing behaviour of <code>smartmatch()</code> by providing a variant for specific cases that the multisub already handles:</p> <pre><code>use Multi::Dispatch; # Change how smartmatch() compares a hash and an array # (The standard behaviour is to match if ANY hash key is present in the array; # but here we change it so that ALL hash keys must be present)... multi smartmatch (HASH $href, ARRAY $aref) { for my $key (keys %{$href}) { return false if !smartmatch($key, $aref); } return true; }</code></pre> <p>For further details on the numerous features and capabilities of the <code>multi</code> keyword, see the <a href="/pod/Multi::Dispatch">Multi::Dispatch</a> module.</p> <h1 id="LIMITATIONS">LIMITATIONS</h1> <p>The re-implementation of <code>given</code>/<code>when</code> provided by this module aims to be fully backwards compatible with the former built-in <code>given</code>/<code>when</code> construct, but currently fails to meet that goal in several ways:</p> <h2 id="Limitation-1.-You-can&#39;t-always-use-a-given-inside-a-do-block"><a id="Limitation"></a><a id="Limitation-1.-You-cant-always-use-a-given-inside-a-do-block"></a>Limitation 1. You can&#39;t always use a <code>given</code> inside a <code>do</code> block</h2> <p>The former built-in switch feature allowed you to place a <code>given</code> inside a <code>do</code> block and then use a series of <code>when</code> blocks to select the result of the <code>do</code>. Like so:</p> <pre><code>my $result = do { given ($some_value) { when (undef) { &#39;undef&#39; } when (any =&gt; [0..9]) { &#39;digit&#39; } break when /skip/; when (&#39;quit&#39;) { &#39;exit&#39; } default { &#39;huh?&#39; } } };</code></pre> <p>The module currently only supports a limited subset of that capability. For example, the above code will still compile and execute, but the value assigned to <code>$result</code> will always be undefined, regardless of the contents of <code>$some_value</code>.</p> <p>This is because it seems to be impossible to fully emulate the implicit flow control at the end of a <code>when</code> block <i>(i.e. automatically jumping out of the surrounding <code>given</code> after the last statement in a <code>when</code>)</i> by using other standard Perl constructs. Likewise, to emulate the explicit control flow provided by <code>continue</code> and <code>break</code>, the code has to be translated by adding at least one extra statement after the block of each <code>given</code> and <code>when</code>.</p> <p>So it does not seem possible to rewrite an arbitrary <code>given</code>/<code>when</code> such that the last statement in a <code>when</code> is also the last executed statement in its <code>given</code>, and hence is the last executed statement in the surrounding <code>do</code> block.</p> <p>However, the module is able to correctly rewrite at least <i>some</i> (perhaps <i>most</i>) <code>given</code>/<code>when</code> combinations so that they work correctly within a <code>do</code> block. Specifically, as long as a <code>given</code>&#39;s block <b>does not</b> contain an explicit <code>continue</code> or <code>break</code> or <code>goto</code>, or a postfix <code>when</code> statement modifier, then the module optimizes its rewriting of the entire <code>given</code>, converting it into a form that <i>can</i> be placed inside a <code>do</code> block and still successfully produce values. Hence, although the previous example did not work, if the <code>break when...</code> statement it contains were removed:</p> <pre><code>my $result = do { given ($some_value) { when (undef) { &#39;undef&#39; } when (any =&gt; [0..9]) { &#39;digit&#39; } # &lt;-- POSTFIX when REMOVED when (&#39;quit&#39;) { &#39;exit&#39; } default { &#39;huh?&#39; } } };</code></pre> <p>...or even if the postfix <code>when</code> were converted to the equivalent <code>when</code> block:</p> <pre><code>my $result = do { given ($some_value) { when (undef) { &#39;undef&#39; } when (any =&gt; [0..9]) { &#39;digit&#39; } when (/skip/) { undef } # &lt;-- CONVERTED FROM POSTFIX when (&#39;quit&#39;) { &#39;exit&#39; } default { &#39;huh?&#39; } } };</code></pre> <p>...then the code <b>would</b> work as expected and <code>$result</code> would receive an appropriate value.</p> <p>In general, if you have written a <code>do</code> block with a nested <code>given</code>/<code>when</code> that is <b>not</b> going to work under this module, you will usually receive a series of compile-time <i>&quot;Useless use of a constant in void context&quot;</i> warnings, one for each <code>when</code> block.</p> <p>See the file <i>t/given_when.t</i> for examples of this construction that do work, and the file <i>t/given_when_noncompatible.t</i> for examples the will not (currently, or probably ever) work.</p> <h2 id="2.-Use-of-when-modifiers-outside-a-given"><a id="21"></a><a id="Use-of-when-modifiers-outside-a-given"></a>2. Use of <code>when</code> modifiers outside a <code>given</code></h2> <p>The former built-in mechanism allowed a postfix <code>when</code> modifier to be used within a <code>for</code> loop, like so:</p> <pre><code>for (@data) { say when @target_value; }</code></pre> <p>This module does not allow <code>when</code> to be used as a statement modifier anywhere except inside a <code>given</code> block. The above code would therefore have to be rewritten to either:</p> <pre><code>for (@data) { given ($) { say when @target_value; } }</code></pre> <p>...or to:</p> <pre><code>for (@data) { when (@target_value) { say } }</code></pre> <h2 id="3.-Scoping-anomalies-of-when-modifiers"><a id="3"></a><a id="Scoping-anomalies-of-when-modifiers"></a>3. Scoping anomalies of <code>when</code> modifiers</h2> <p>The behaviour of obscure usages such as:</p> <pre><code>my $x = 0; given (my $x = 1) { my $x = 2, continue when 1; say $x; }</code></pre> <p>...differs between the built-in <code>given</code>/<code>when</code> and this module&#39;s reimplementation. Under the built-in feature, <code>$x</code> contains <code>undef</code> at the <span style="white-space: nowrap;"><code>say $x</code></span> line; under the module, <code>$x</code> contains 2.</p> <p>As neither result seems to make much sense, or be particularly useful, it is unlikely that this backwards incompatibility will ever be rectified.</p> <h1 id="DIAGNOSTICS">DIAGNOSTICS</h1> <dl> <dt id="Incomprehensible-&quot;when&quot;"><a id="Incomprehensible"></a><a id="Incomprehensible-when"></a><code>Incomprehensible &quot;when&quot;</code></dt> <dd> </dd> <dt id="Incomprehensible-&quot;default&quot;"><a id="Incomprehensible1"></a><a id="Incomprehensible-default"></a><code>Incomprehensible &quot;default&quot;</code></dt> <dd> <p>You specified a <code>when</code> or <code>default</code> keyword, but the code following it did not conform to the correct syntax for those blocks. The error message will attempt to indicate where the problem was, but that indication may not be accurate.</p> <p>Check the syntax of your block.</p> </dd> <dt id="Can&#39;t-&quot;when&quot;-outside-a-topicalizer"><a id="Can"></a><a id="Cant-when-outside-a-topicalizer"></a><code>Can&#39;t &quot;when&quot; outside a topicalizer</code></dt> <dd> </dd> <dt id="Can&#39;t-&quot;default&quot;-outside-a-topicalizer"><a id="Can1"></a><a id="Cant-default-outside-a-topicalizer"></a><code>Can&#39;t &quot;default&quot; outside a topicalizer</code></dt> <dd> <p><code>when</code> and <code>default</code> blocks can only be executed inside a <code>given</code> or a <code>for</code> loop. Your code is attempting to execute a <code>when</code> or <code>default</code> somewhere else. That never worked with the built-in syntax, and so it doesn&#39;t work with this module either.</p> <p>Move your block inside a <code>given</code> or a <code>for</code> loop.</p> </dd> <dt id="Can&#39;t-specify-postfix-&quot;when&quot;-modifier-outside-a-&quot;given&quot;"><a id="Can2"></a><a id="Cant-specify-postfix-when-modifier-outside-a-given"></a><code>Can&#39;t specify postfix &quot;when&quot; modifier outside a &quot;given&quot;</code></dt> <dd> <p>It is a limitation of this module that you can only use the <code>EXPR when EXPR</code> syntax inside a <code>given</code> (not inside a <code>for</code> loop). And, of course, you couldn&#39;t ever use it outside of both.</p> <p>If your postfix <code>when</code> is inside a loop, convert it to a <code>when</code> block instead.</p> </dd> <dt id="Can&#39;t-&quot;continue&quot;-outside-a-&quot;when&quot;-or-&quot;default&quot;"><a id="Can3"></a><a id="Cant-continue-outside-a-when-or-default"></a><code>Can&#39;t &quot;continue&quot; outside a &quot;when&quot; or &quot;default&quot;</code></dt> <dd> <p>Calling a <code>continue</code> to override the automatic <span style="white-space: nowrap;"><i>&quot;jump-out-of-the-surrounding-<code>given</code>&quot;</i></span> behaviour of <code>when</code> and <code>default</code> blocks only makes sense if you&#39;re actually inside a <code>when</code> or a <code>default</code>. However, your code is attempting to call <code>continue</code> somewhere else.</p> <p>Move your <code>continue</code> inside a <code>when</code> or a <code>default</code>.</p> </dd> <dt id="Can&#39;t-&quot;break&quot;-outside-a-&quot;given&quot;"><a id="Can4"></a><a id="Cant-break-outside-a-given"></a><code>Can&#39;t &quot;break&quot; outside a &quot;given&quot;</code></dt> <dd> <p>Calling a <code>break</code> to explicitly <span style="white-space: nowrap;"><i>&quot;jump-out-of-the-surrounding-<code>given</code>&quot;</i></span> only makes sense when you&#39;re inside a <code>given</code> in the first place.</p> <p>Move your <code>break</code> inside a <code>given</code>.</p> <p>Or, if you&#39;re trying to escape from a <code>when</code> in a loop, change <code>break</code> to <code>next</code> or <code>last</code>.</p> </dd> <dt id="Smart-matching-an-object-breaks-encapsulation"><a id="Smart"></a><code>Smart matching an object breaks encapsulation</code></dt> <dd> <p>This module does not support the smartmatching of objects (because from Perl v5.42 onwards there is no way to overload <code>~~</code> for an object).</p> <p>If you want to use an object in a <code>given</code> or <code>when</code>, you will need to provide a variant of <code>smartmatch()</code> that handles that kind of object. See <a href="#Overloading-smartmatch()">&quot;Overloading <code>smartmatch()</code>&quot;</a> for details of how to do that.</p> </dd> <dt id="Use-of-uninitialized-value-in-pattern-match"><a id="Use"></a><code>Use of uninitialized value in pattern match</code></dt> <dd> </dd> <dt id="Use-of-uninitialized-value-in-smartmatch"><a id="Use1"></a><code>Use of uninitialized value in smartmatch</code></dt> <dd> <p>You passed a value to <code>given</code> or <code>when</code> that included an <code>undef</code>, which was subsequently matched against a regex or against some other defined value. The former <code>~~</code> operator warned about this in some cases, so the <code>smartmatch()</code> subroutine does too.</p> <p>To silence this warning, add:</p> <pre><code>no warnings &#39;uninitialized&#39;;</code></pre> <p>before the attempted smartmatch.</p> </dd> </dl> <h1 id="CONFIGURATION-AND-ENVIRONMENT"><a id="CONFIGURATION"></a>CONFIGURATION AND ENVIRONMENT</h1> <p>Switch::Back requires no configuration files or environment variables.</p> <h1 id="DEPENDENCIES">DEPENDENCIES</h1> <p>This module requires the <a href="/pod/Multi::Dispatch">Multi::Dispatch</a>, <a href="/pod/PPR">PPR</a>, <a href="/pod/Keyword::Simple">Keyword::Simple</a>, and <a href="/pod/Type::Tiny">Type::Tiny</a> modules.</p> <h1 id="INCOMPATIBILITIES">INCOMPATIBILITIES</h1> <p>This module uses the Perl keyword mechanism to (re)extend the Perl syntax to include <code>given</code>/<code>when</code>/<code>default</code> blocks. Hence it is likely to be incompatible with other modules that add other keywords to the language.</p> <h1 id="BUGS">BUGS</h1> <p>No bugs have been reported.</p> <p>Please report any bugs or feature requests to <code>bug-switch-back@rt.cpan.org</code>, or through the web interface at <a href="http://rt.cpan.org">http://rt.cpan.org</a>.</p> <h1 id="SEE-ALSO"><a id="SEE"></a>SEE ALSO</h1> <p>The <a href="/pod/Switch::Right">Switch::Right</a> module provides a kinder gentler approach to replacing the now defunct switch and smartmatch features.</p> <h1 id="AUTHOR">AUTHOR</h1> <p>Damian Conway <code>&lt;DCONWAY@CPAN.org&gt;</code></p> <h1 id="LICENCE-AND-COPYRIGHT"><a id="LICENCE"></a>LICENCE AND COPYRIGHT</h1> <p>Copyright (c) 2024, Damian Conway <code>&lt;DCONWAY@CPAN.org&gt;</code>. All rights reserved.</p> <p>This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See <a href="/pod/perlartistic">perlartistic</a>.</p> <h1 id="DISCLAIMER-OF-WARRANTY"><a id="DISCLAIMER"></a>DISCLAIMER OF WARRANTY</h1> <p>BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.</p> <p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p></div> <div id="metacpan_install-instructions-dialog" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <h4 class="modal-title">Module Install Instructions</h4> </div> <div class="modal-body"> <p>To install Switch::Back, copy and paste the appropriate command in to your terminal.</p> <p><a href="/dist/App-cpanminus/view/bin/cpanm">cpanm</a></p> <pre><code>cpanm Switch::Back</code></pre> <p><a href="/pod/CPAN">CPAN shell</a></p> <pre><code>perl -MCPAN -e shell install Switch::Back</code></pre> <p>For more information on module installation, please visit <a href="https://www.cpan.org/modules/INSTALL.html">the detailed CPAN module installation guide</a>.</p> </div> <div class="modal-footer"> <a href="#" data-dismiss="modal" class="btn">Close</a> </div> </div> </div> </div> </main> <div class="content-pagination"> </div> </div> <footer class="footer"> <div class="footer-container"> <div class="footer-social"> <div class="footer-link footer-logo"> <a href="/"> <img src="/static/images/metacpan-logo.svg" alt="MetaCPAN" /> </a> </div> <a class="footer-social-link" href="https://github.com/metacpan"> <i class="fab fa-github-square"></i> </a> <a class="footer-social-link" href="https://fosstodon.org/@metacpan"> <i class="fab fa-mastodon"></i> </a> </div> <div class="footer-links"> <div class="footer-link"> <a href="/about">About</a> </div> <div class="footer-link"> <a href="/about/sponsors">Sponsor</a> </div> <div class="footer-link"> <a href="https://grep.metacpan.org">grep::cpan</a> </div> <div class="footer-link"> <a href="/recent">Recent</a> </div> <div class="footer-link"> <a href="/about/faq">FAQ</a> </div> <div class="footer-link"> <a href="/tools">Tools</a> </div> <div class="footer-link"> <a href="https://fastapi.metacpan.org/">API</a> </div> <div class="footer-link"> <a href="https://www.perl.org/">Perl.org</a> </div> </div> <div class="footer-sponsors"> <a class="footer-sponsor-link" target="_blank" href="https://www.bytemark.co.uk/" rel="noopener"> <img class="footer-sponsor-bytemark" src="/static/images/sponsors/bytemark_logo.svg" alt="Bytemark logo"> </a> <a class="footer-sponsor-link" target="_blank" href="https://www.liquidweb.com/" rel="noopener"> <img class="footer-sponsor-liquidweb" src="/static/images/sponsors/liquidweb_logo.png" alt="liquidweb logo"> </a> <a class="footer-sponsor-link" target="_blank" href="https://deriv.com/careers/" rel="noopener"> <img class="footer-sponsor-deriv" src="/static/images/sponsors/deriv.svg" alt="Deriv logo"> </a> <a class="footer-sponsor-link" target="_blank" href="https://geocode.xyz" rel="noopener"> <img class="footer-sponsor-geocode" src="/static/images/sponsors/geocodelogo.svg" alt="Geocode logo"> </a> <a class="footer-sponsor-link" target="_blank" href="https://www.fastly.com/" rel="noopener"> <img class="footer-sponsor-fastly" src="/static/images/sponsors/fastly_logo.svg" alt="Fastly logo"> </a> <a class="footer-sponsor-link" target="_blank" href="https://opencagedata.com" rel="noopener"> <img class="footer-sponsor-opencage" src="/static/images/sponsors/open-cage.svg" alt="OpenCage logo"> </a> <!-- Added 2024-07-22 --> <a class="footer-sponsor-link" target="_blank" href="https://www.elastic.co/" rel="noopener"> <img class="footer-sponsor-elastic" src="/static/images/sponsors/elastic.svg" alt="Elastic logo"> </a> <!-- Added 2024-07-22 --> <a class="footer-sponsor-link" target="_blank" href="https://route4me.com/" rel="noopener"> <img class="footer-sponsor-route4me" src="/static/images/sponsors/route4me.png" alt="Route4Me logo"> </a> </div> </div> </footer> <div class="modal fade" tabindex="-1" role="dialog" id="metacpan_keyboard-shortcuts"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">&times;</button> <h4 class="modal-title">Keyboard Shortcuts</h4> </div> <div class="modal-body row"> <div class="col-md-6"> <table class="table keyboard-shortcuts"> <thead> <tr> <th></th> <th>Global</th> </tr> </thead> <tbody> <tr> <td class="keys"> <kbd>s</kbd> </td> <td>Focus search bar</td> </tr> <tr> <td class="keys"> <kbd>?</kbd> </td> <td>Bring up this help dialog</td> </tr> </tbody> </table> <table class="table keyboard-shortcuts"> <thead> <tr> <th></th> <th>GitHub</th> </tr> </thead> <tbody> <tr> <td class="keys"> <kbd>g</kbd> <kbd>p</kbd> </td> <td>Go to pull requests</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>i</kbd> </td> <td>go to github issues (only if github is preferred repository)</td> </tr> </tbody> </table> </div> <div class="col-md-6"> <table class="table keyboard-shortcuts"> <thead> <tr> <th></th> <th>POD</th> </tr> </thead> <tbody> <tr> <td class="keys"> <kbd>g</kbd> <kbd>a</kbd> </td> <td>Go to author</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>c</kbd> </td> <td>Go to changes</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>i</kbd> </td> <td>Go to issues</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>d</kbd> </td> <td>Go to dist</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>r</kbd> </td> <td>Go to repository/SCM</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>s</kbd> </td> <td>Go to source</td> </tr> <tr> <td class="keys"> <kbd>g</kbd> <kbd>b</kbd> </td> <td>Go to file browse</td> </tr> </tbody> </table> </div> <div class="col-md-12"> <table class="table keyboard-shortcuts"> <thead> <tr> <th></th> <th>Search terms</th> </tr> </thead> <tbody> <tr> <td><em>module:</em> (e.g. <a href="/search?q=module%3APlugin">module:Plugin</a>)</td> </tr> <tr> <td><em>distribution:</em> (e.g. <a href="/search?q=distribution%3ADancer+auth">distribution:Dancer auth</a>)</td> </tr> <tr> <td><em>author:</em> (e.g. <a href="/search?q=author%3ASONGMU+Redis">author:SONGMU Redis</a>)</td> </tr> <tr> <td><em>version:</em> (e.g. <a href="/search?q=version%3A1.00">version:1.00</a>)</td> </tr> </tbody> </table> </div> </div> <div class="modal-footer"></div> </div> </div> </div> </body> </html>

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