CINXE.COM
Moops - Moops Object-Oriented Programming Sugar - metacpan.org
<!DOCTYPE html> <html lang="en-US"> <head> <title>Moops - Moops Object-Oriented Programming Sugar - 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 Moops - MetaCPAN" href="/dist/Moops/releases.rss" /> <link rel="canonical" href="https://metacpan.org/pod/Moops" /> <meta name="description" content="Moops Object-Oriented Programming Sugar" /> <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/Moops" /> <meta property="og:title" content="Moops" /> <meta property="og:description" content="Moops Object-Oriented Programming Sugar" /> <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 Moops was released."> <span class="relatize">15 Feb 2020 09:33:03 UTC</span> </div> </li> <li> Distribution: <a href="/dist/Moops">Moops</a> </li> <li> Module version: 0.038 </li> <li> <a data-keyboard-shortcut="g s" href="/dist/Moops/source/lib/Moops.pm">Source</a> (<a href="/dist/Moops/source/lib/Moops.pm?raw=1">raw</a>) </li> <li> <a data-keyboard-shortcut="g b" href="/dist/Moops/source/lib">Browse</a> (<a href="/dist/Moops/source/lib?raw=1">raw</a>) </li> <li> <a data-keyboard-shortcut="g c" href="/dist/Moops/changes">Changes</a> </li> <li> <a rel="noopener nofollow" class="nopopup" href="https://metacpan.org/release/Moops">Homepage</a> </li> <li> <a class="nopopup" href="/dist/Moops/contribute">How to Contribute</a> </li> <li> <a rel="noopener nofollow" data-keyboard-shortcut="g r" href="https://github.com/tobyink/p5-moops">Repository</a> </li> <li> <a rel="noopener nofollow" data-keyboard-shortcut="g i" href="http://rt.cpan.org/Dist/Display.html?Queue=Moops">Issues</a> (2) </li> <li> <a rel="noopener nofollow" href="http://matrix.cpantesters.org/?dist=Moops+0.038" title="Matrix">Testers</a> <span title="(pass / fail / na)">(<a rel="noopener nofollow" href="https://www.cpantesters.org/distro/M/Moops.html?oncpan=1&distmat=1&version=0.038&grade=2" style="color: #090">1387</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/M/Moops.html?oncpan=1&distmat=1&version=0.038&grade=3" style="color: #900">128</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/M/Moops.html?oncpan=1&distmat=1&version=0.038&grade=4">0</a>)</span> </li> <li> <a rel="noopener nofollow" href="http://cpants.cpanauthors.org/release/TOBYINK/Moops-0.038">Kwalitee</a> </li> <li> <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The # people with an indexing permission on Moops 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> <a rel="noopener nofollow" href="http://cpancover.com/latest/Moops-0.038/index.html">90.48% Coverage </a> </li> <li> License: perl_5 </li> <li> Perl: v5.14.0 </li> <li class="nav-header">Activity</li> <li> <div class="activity-graph"> <img src="/dist/Moops/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/T/TO/TOBYINK/Moops-0.038.tar.gz"> Download (<span itemprop="fileSize">62.5KB</span>)</a> </li> <li> <a href="https://explorer.metacpan.org/?url=%2Fmodule%2FTOBYINK%2FMoops-0.038%2Flib%2FMoops.pm"> MetaCPAN Explorer </a> </li> <li> <a href="/dist/Moops/permissions"> Permissions </a> </li> <li> <a href="/dist/Moops/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:Moops"> <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="Moops"> <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/TOBYINK/Moops-0.038/view/lib/Moops.pm" >0.038 (TOBYINK on 2020-02-15)</option> <option value="/release/TOBYINK/Moops-0.037/view/lib/Moops.pm" >0.037 (TOBYINK on 2020-02-13)</option> <optgroup label="BackPAN">' <option value="/release/TOBYINK/Moops-0.036/view/lib/Moops.pm" >0.036 (TOBYINK on 2018-08-09)</option> <option value="/release/TOBYINK/Moops-0.035/view/lib/Moops.pm" >0.035 (TOBYINK on 2018-06-26)</option> <option value="/release/TOBYINK/Moops-0.034/view/lib/Moops.pm" >0.034 (TOBYINK on 2014-10-12)</option> <option value="/release/TOBYINK/Moops-0.033/view/lib/Moops.pm" >0.033 (TOBYINK on 2014-08-16)</option> <option value="/release/TOBYINK/Moops-0.032/view/lib/Moops.pm" >0.032 (TOBYINK on 2014-08-13)</option> <option value="/release/TOBYINK/Moops-0.031/view/lib/Moops.pm" >0.031 (TOBYINK on 2014-03-23)</option> <option value="/release/TOBYINK/Moops-0.030/view/lib/Moops.pm" >0.030 (TOBYINK on 2014-01-30)</option> <option value="/release/TOBYINK/Moops-0.029/view/lib/Moops.pm" >0.029 (TOBYINK on 2014-01-04)</option> <option value="/release/TOBYINK/Moops-0.028/view/lib/Moops.pm" >0.028 (TOBYINK on 2013-12-18)</option> <option value="/release/TOBYINK/Moops-0.027/view/lib/Moops.pm" >0.027 (TOBYINK on 2013-12-16)</option> <option value="/release/TOBYINK/Moops-0.026/view/lib/Moops.pm" >0.026 (TOBYINK on 2013-11-18)</option> <option value="/release/TOBYINK/Moops-0.025/view/lib/Moops.pm" >0.025 (TOBYINK on 2013-10-09)</option> <option value="/release/TOBYINK/Moops-0.024/view/lib/Moops.pm" >0.024 (TOBYINK on 2013-09-27)</option> <option value="/release/TOBYINK/Moops-0.023/view/lib/Moops.pm" >0.023 (TOBYINK on 2013-09-26)</option> <option value="/release/TOBYINK/Moops-0.022/view/lib/Moops.pm" >0.022 (TOBYINK on 2013-09-16)</option> <option value="/release/TOBYINK/Moops-0.021/view/lib/Moops.pm" >0.021 (TOBYINK on 2013-09-12)</option> <option value="/release/TOBYINK/Moops-0.020/view/lib/Moops.pm" >0.020 (TOBYINK on 2013-09-11)</option> <option value="/release/TOBYINK/Moops-0.019/view/lib/Moops.pm" >0.019 (TOBYINK on 2013-08-30)</option> <option value="/release/TOBYINK/Moops-0.018/view/lib/Moops.pm" >0.018 (TOBYINK on 2013-08-27)</option> <option value="/release/TOBYINK/Moops-0.017/view/lib/Moops.pm" >0.017 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.016/view/lib/Moops.pm" >0.016 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.015/view/lib/Moops.pm" >0.015 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.014/view/lib/Moops.pm" >0.014 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.013/view/lib/Moops.pm" >0.013 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.012/view/lib/Moops.pm" >0.012 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.011/view/lib/Moops.pm" >0.011 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.010/view/lib/Moops.pm" >0.010 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.009/view/lib/Moops.pm" >0.009 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.008/view/lib/Moops.pm" >0.008 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.007/view/lib/Moops.pm" >0.007 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.006/view/lib/Moops.pm" >0.006 (TOBYINK on 2013-08-16)</option> </optgroup> </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/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.038/lib/Moops.pm" >0.038 (TOBYINK on 2020-02-15)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.037/lib/Moops.pm" >0.037 (TOBYINK on 2020-02-13)</option> <optgroup label="BackPAN">' <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.036/lib/Moops.pm" >0.036 (TOBYINK on 2018-08-09)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.035/lib/Moops.pm" >0.035 (TOBYINK on 2018-06-26)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.034/lib/Moops.pm" >0.034 (TOBYINK on 2014-10-12)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.033/lib/Moops.pm" >0.033 (TOBYINK on 2014-08-16)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.032/lib/Moops.pm" >0.032 (TOBYINK on 2014-08-13)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.031/lib/Moops.pm" >0.031 (TOBYINK on 2014-03-23)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.030/lib/Moops.pm" >0.030 (TOBYINK on 2014-01-30)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.029/lib/Moops.pm" >0.029 (TOBYINK on 2014-01-04)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.028/lib/Moops.pm" >0.028 (TOBYINK on 2013-12-18)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.027/lib/Moops.pm" >0.027 (TOBYINK on 2013-12-16)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.026/lib/Moops.pm" >0.026 (TOBYINK on 2013-11-18)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.025/lib/Moops.pm" >0.025 (TOBYINK on 2013-10-09)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.024/lib/Moops.pm" >0.024 (TOBYINK on 2013-09-27)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.023/lib/Moops.pm" >0.023 (TOBYINK on 2013-09-26)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.022/lib/Moops.pm" >0.022 (TOBYINK on 2013-09-16)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.021/lib/Moops.pm" >0.021 (TOBYINK on 2013-09-12)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.020/lib/Moops.pm" >0.020 (TOBYINK on 2013-09-11)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.019/lib/Moops.pm" >0.019 (TOBYINK on 2013-08-30)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.018/lib/Moops.pm" >0.018 (TOBYINK on 2013-08-27)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.017/lib/Moops.pm" >0.017 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.016/lib/Moops.pm" >0.016 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.015/lib/Moops.pm" >0.015 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.014/lib/Moops.pm" >0.014 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.013/lib/Moops.pm" >0.013 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.012/lib/Moops.pm" >0.012 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.011/lib/Moops.pm" >0.011 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.010/lib/Moops.pm" >0.010 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.009/lib/Moops.pm" >0.009 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.008/lib/Moops.pm" >0.008 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.007/lib/Moops.pm" >0.007 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.038/diff/TOBYINK/Moops-0.006/lib/Moops.pm" >0.006 (TOBYINK on 2013-08-16)</option> </optgroup> </select> </li> <li> <ul class="dependencies"> <li class="nav-header">Dependencies</li> <li><a href="/pod/Devel::GlobalDestruction" title="Devel::GlobalDestruction" class="ellipsis">Devel::GlobalDestruction</a></li> <li><a href="/pod/Exporter::Tiny" title="Exporter::Tiny" class="ellipsis">Exporter::Tiny</a></li> <li><a href="/pod/Import::Into" title="Import::Into" class="ellipsis">Import::Into</a></li> <li><a href="/pod/Kavorka" title="Kavorka" class="ellipsis">Kavorka</a></li> <li><a href="/pod/Keyword::Simple" title="Keyword::Simple" class="ellipsis">Keyword::Simple</a></li> <li><a href="/pod/Lexical::Accessor" title="Lexical::Accessor" class="ellipsis">Lexical::Accessor</a></li> <li><a href="/pod/Module::Runtime" title="Module::Runtime" class="ellipsis">Module::Runtime</a></li> <li><a href="/pod/Moo" title="Moo" class="ellipsis">Moo</a></li> <li><a href="/pod/MooX::late" title="MooX::late" class="ellipsis">MooX::late</a></li> <li><a href="/pod/MooseX::MungeHas" title="MooseX::MungeHas" class="ellipsis">MooseX::MungeHas</a></li> <li><a href="/pod/Parse::Keyword" title="Parse::Keyword" class="ellipsis">Parse::Keyword</a></li> <li><a href="/pod/PerlX::Assert" title="PerlX::Assert" class="ellipsis">PerlX::Assert</a></li> <li><a href="/pod/PerlX::Define" title="PerlX::Define" class="ellipsis">PerlX::Define</a></li> <li><a href="/pod/Scalar::Util" title="Scalar::Util" class="ellipsis">Scalar::Util</a></li> <li><a href="/pod/Try::Tiny" title="Try::Tiny" class="ellipsis">Try::Tiny</a></li> <li><a href="/pod/Type::Utils" title="Type::Utils" class="ellipsis">Type::Utils</a></li> <li><a href="/pod/Variable::Magic" title="Variable::Magic" class="ellipsis">Variable::Magic</a></li> <li><a href="/pod/namespace::autoclean" title="namespace::autoclean" class="ellipsis">namespace::autoclean</a></li> <li><a href="/pod/strictures" title="strictures" class="ellipsis">strictures</a></li> <li><a href="/pod/true" title="true" class="ellipsis">true</a></li> <li><i class="ttip" title="dynamic_config enabled">and possibly others</i></li> <li> <hr> </li> <li> <a href="/module/Moops/requires">Reverse dependencies</a> </li> <li> <a href="http://deps.cpantesters.org/?module=Moops">CPAN Testers List</a> </li> <li> <a href="https://cpandeps.grinnz.com/?dist=Moops">Dependency graph</a> </li> </ul> </li> <li class="nav-header">Permalinks</li> <li> <a href="/release/TOBYINK/Moops-0.038/view/lib/Moops.pm">This version</a> </li> <li> <a href="/pod/Moops">Latest version</a> </li> <li> <div class="plussers"> <div class="nav-header">++ed by:</div> <div> <a class="display-all" href="/author/JAYALLEN"><img src="https://www.gravatar.com/avatar/34e155145f5145d2e30979313b334327?d=identicon&s=20" title="JAYALLEN" alt="JAYALLEN"></a> <a class="display-all" href="/author/ANDREFS"><img src="https://www.gravatar.com/avatar/d2c0a12ed7d62d701e2d225cd7b70b61?d=identicon&s=20" title="ANDREFS" alt="ANDREFS"></a> <a class="display-all" href="/author/RRWO"><img src="https://www.gravatar.com/avatar/4a5274bc5d690ee3d619f044778771a7?d=identicon&s=20" title="RRWO" alt="RRWO"></a> <a class="display-all" href="/author/EMAZEP"><img src="https://www.gravatar.com/avatar/a700b943268e8937ffd425389d962787?d=identicon&s=20" title="EMAZEP" alt="EMAZEP"></a> <a class="display-all" href="/author/RPAVLOV"><img src="https://www.gravatar.com/avatar/93bf56fc3fcce8fbfe5eb792767f377e?d=identicon&s=20" title="RPAVLOV" alt="RPAVLOV"></a> </div> <!-- Display counts of plussers--> <div> <a href="/dist/Moops/plussers">28 PAUSE users</a> </div> <div> 25 non-PAUSE users </div> </div> </li> <li> <div> <button class="contributors-show-button btn-link">and 2 contributors</button> <div id="metacpan_contributors" class="slide-out slide-out-hidden"> <div> <ul> <li class="contributor" data-cpan-author="TEEJAY" data-contrib-email="teejay@cpan.org" > <a href="/author/TEEJAY" class="cpan-author"> <img class="gravatar" width="20" height="20" src="https://www.gravatar.com/avatar/1fdcfca4c68559a8b7ab2aabd7c10e70?d=identicon&s=20" /> Aaron James Trevena (TEEJAY) </a> </li> <li class="contributor" data-cpan-author="MMAURICE" data-contrib-email="mmaurice@cpan.org" > <a href="/author/MMAURICE" class="cpan-author"> <img class="gravatar" width="20" height="20" src="https://www.gravatar.com/avatar/6c05bb5acd457f54dbde33465359997f?d=identicon&s=20" /> Maurice Mengel (MMAURICE) </a> </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/TOBYINK" class="author-name">Toby Inkster</a> </span> <span> / </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/TOBYINK/Moops-0.038/view/lib/Moops.pm" >0.038 (TOBYINK on 2020-02-15)</option> <option value="/release/TOBYINK/Moops-0.037/view/lib/Moops.pm" >0.037 (TOBYINK on 2020-02-13)</option> <optgroup label="BackPAN">' <option value="/release/TOBYINK/Moops-0.036/view/lib/Moops.pm" >0.036 (TOBYINK on 2018-08-09)</option> <option value="/release/TOBYINK/Moops-0.035/view/lib/Moops.pm" >0.035 (TOBYINK on 2018-06-26)</option> <option value="/release/TOBYINK/Moops-0.034/view/lib/Moops.pm" >0.034 (TOBYINK on 2014-10-12)</option> <option value="/release/TOBYINK/Moops-0.033/view/lib/Moops.pm" >0.033 (TOBYINK on 2014-08-16)</option> <option value="/release/TOBYINK/Moops-0.032/view/lib/Moops.pm" >0.032 (TOBYINK on 2014-08-13)</option> <option value="/release/TOBYINK/Moops-0.031/view/lib/Moops.pm" >0.031 (TOBYINK on 2014-03-23)</option> <option value="/release/TOBYINK/Moops-0.030/view/lib/Moops.pm" >0.030 (TOBYINK on 2014-01-30)</option> <option value="/release/TOBYINK/Moops-0.029/view/lib/Moops.pm" >0.029 (TOBYINK on 2014-01-04)</option> <option value="/release/TOBYINK/Moops-0.028/view/lib/Moops.pm" >0.028 (TOBYINK on 2013-12-18)</option> <option value="/release/TOBYINK/Moops-0.027/view/lib/Moops.pm" >0.027 (TOBYINK on 2013-12-16)</option> <option value="/release/TOBYINK/Moops-0.026/view/lib/Moops.pm" >0.026 (TOBYINK on 2013-11-18)</option> <option value="/release/TOBYINK/Moops-0.025/view/lib/Moops.pm" >0.025 (TOBYINK on 2013-10-09)</option> <option value="/release/TOBYINK/Moops-0.024/view/lib/Moops.pm" >0.024 (TOBYINK on 2013-09-27)</option> <option value="/release/TOBYINK/Moops-0.023/view/lib/Moops.pm" >0.023 (TOBYINK on 2013-09-26)</option> <option value="/release/TOBYINK/Moops-0.022/view/lib/Moops.pm" >0.022 (TOBYINK on 2013-09-16)</option> <option value="/release/TOBYINK/Moops-0.021/view/lib/Moops.pm" >0.021 (TOBYINK on 2013-09-12)</option> <option value="/release/TOBYINK/Moops-0.020/view/lib/Moops.pm" >0.020 (TOBYINK on 2013-09-11)</option> <option value="/release/TOBYINK/Moops-0.019/view/lib/Moops.pm" >0.019 (TOBYINK on 2013-08-30)</option> <option value="/release/TOBYINK/Moops-0.018/view/lib/Moops.pm" >0.018 (TOBYINK on 2013-08-27)</option> <option value="/release/TOBYINK/Moops-0.017/view/lib/Moops.pm" >0.017 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.016/view/lib/Moops.pm" >0.016 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.015/view/lib/Moops.pm" >0.015 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.014/view/lib/Moops.pm" >0.014 (TOBYINK on 2013-08-21)</option> <option value="/release/TOBYINK/Moops-0.013/view/lib/Moops.pm" >0.013 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.012/view/lib/Moops.pm" >0.012 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.011/view/lib/Moops.pm" >0.011 (TOBYINK on 2013-08-20)</option> <option value="/release/TOBYINK/Moops-0.010/view/lib/Moops.pm" >0.010 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.009/view/lib/Moops.pm" >0.009 (TOBYINK on 2013-08-19)</option> <option value="/release/TOBYINK/Moops-0.008/view/lib/Moops.pm" >0.008 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.007/view/lib/Moops.pm" >0.007 (TOBYINK on 2013-08-18)</option> <option value="/release/TOBYINK/Moops-0.006/view/lib/Moops.pm" >0.006 (TOBYINK on 2013-08-16)</option> </optgroup> </select> <a data-keyboard-shortcut="g d" class="release-name" href="/dist/Moops">Moops-0.038</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 two • 17 direct dependents • 18 total dependents </title> <rect x="0" y="0" width="4" height="15" fill="#7ea3f2" /> <rect x="5" y="0" width="4" height="15" fill="#7ea3f2" /> <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="Moops-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="Moops-0.038"> <input type="hidden" name="author" value="TOBYINK"> <input type="hidden" name="distribution" value="Moops"> <button type="submit" class="favorite highlight"><span>53</span> ++</button> </form> </div> <div class="show-logged-out"> <button class="fav-not-logged-in favorite highlight"><span>53</span> ++</button> </div> / <span>Moops</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="#SYNOPSIS">SYNOPSIS</a></li> <li><a href="#STATUS">STATUS</a></li> <li><a href="#DESCRIPTION">DESCRIPTION</a> <ul> <li><a href="#Classes">Classes</a></li> <li><a href="#Roles">Roles</a> <ul> <li><a href="#A-note-on-consuming-roles">A note on consuming roles</a></li> </ul> </li> <li><a href="#Namespaces">Namespaces</a></li> <li><a href="#Functions-and-Methods">Functions and Methods</a></li> <li><a href="#Method-Modifiers">Method Modifiers</a></li> <li><a href="#Multi-Methods">Multi Methods</a></li> <li><a href="#Type-Constraints">Type Constraints</a></li> <li><a href="#Type-Libraries">Type Libraries</a></li> <li><a href="#Constants">Constants</a></li> <li><a href="#Assertions">Assertions</a></li> <li><a href="#More-Sugar">More Sugar</a></li> <li><a href="#Outer-Sugar">Outer Sugar</a></li> <li><a href="#Custom-Sugar">Custom Sugar</a></li> </ul> </li> <li><a href="#EXTENDING">EXTENDING</a> <ul> <li><a href="#Extending-Moops-via-imports">Extending Moops via imports</a></li> <li><a href="#Extending-Moops-via-keyword-traits">Extending Moops via keyword traits</a></li> <li><a href="#Extending-Moops-via-parser-traits">Extending Moops via parser traits</a></li> </ul> </li> <li><a href="#BUGS">BUGS</a></li> <li><a href="#GOTCHAS">GOTCHAS</a></li> <li><a href="#SUPPORT">SUPPORT</a></li> <li><a href="#SEE-ALSO">SEE ALSO</a></li> <li><a href="#AUTHOR">AUTHOR</a></li> <li><a href="#COPYRIGHT-AND-LICENCE">COPYRIGHT AND LICENCE</a></li> <li><a href="#DISCLAIMER-OF-WARRANTIES">DISCLAIMER OF WARRANTIES</a></li> </ul></nav> <div class="pod anchors"> <h1 id="NAME">NAME</h1> <p>Moops - Moops Object-Oriented Programming Sugar</p> <h1 id="SYNOPSIS">SYNOPSIS</h1> <pre><code>use Moops; role NamedThing { has name => (is => "ro", isa => Str); } class Person with NamedThing; class Company with NamedThing; class Employee extends Person { has job_title => (is => "rwp", isa => Str); has employer => (is => "rwp", isa => InstanceOf["Company"]); method change_job ( Object $employer, Str $title ) { $self->_set_job_title($title); $self->_set_employer($employer); } method promote ( Str $title ) { $self->_set_job_title($title); } }</code></pre> <h1 id="STATUS">STATUS</h1> <p>Unstable.</p> <p>Will probably never be stable.</p> <p>A lot of the modules that Moops is built on have problems. In particular, <a href="/pod/Devel::CallParser">Devel::CallParser</a> is broken on a lot of Perl versions, and <a href="/pod/Parse::Keyword">Parse::Keyword</a> has <i>fundamental errors in the way it handles closures</i> (which Moops works around using <a href="/pod/PadWalker">PadWalker</a>).</p> <p>Moops will remain on CPAN for the foreseeable future and I'll continue to accept patches that fix bugs, but don't expect any new features to be added.</p> <p>For a replacement, consider <a href="/pod/Zydeco">Zydeco</a>. It's not a drop-in replacement but it has a similar syntax to Moops, and provides many of the same features.</p> <h1 id="DESCRIPTION">DESCRIPTION</h1> <p>Moops is sugar for declaring and using roles and classes in Perl.</p> <p>The syntax is inspired by <a href="/pod/MooseX::Declare">MooseX::Declare</a>, and Stevan Little's p5-mop-redux project (which is in turn partly inspired by Perl 6).</p> <p>Moops has fewer than half of the dependencies as MooseX::Declare, loads in about 25% of the time, and the classes built with it run significantly faster. Moops does not use Devel::Declare, instead using Perl's pluggable keyword API; <i>this requires Perl 5.14 or above</i>.</p> <p>Moops uses <a href="/pod/Moo">Moo</a> to build classes and roles by default, but allows you to use <a href="/pod/Moose">Moose</a> if you desire. (And <a href="/pod/Mouse">Mouse</a> experimentally.)</p> <h2 id="Classes">Classes</h2> <p>The <code>class</code> keyword declares a class:</p> <pre><code>class Foo { # ... }</code></pre> <p>A version number can be provided:</p> <pre><code>class Foo 1.2 { # ... }</code></pre> <p>If no version is provided, your class' <code>$VERSION</code> variable is set to the empty string; this helps the package be seen by <a href="/pod/Class::Load">Class::Load</a>.</p> <p>If your class extends an existing class through inheritance, or consumes one or more roles, these can also be provided when declaring the class.</p> <pre><code>class Foo::Bar 1.2 extends Foo 1.1 with Magic::Monkeys { # ... }</code></pre> <p>If you use Moops within a package other than <code>main</code>, then package names used within the declaration are "qualified" by that outer package, unless they contain "::". So for example:</p> <pre><code>package Quux; use Moops; class Foo { } # declares Quux::Foo class Xyzzy::Foo # declares Xyzzy::Foo extends Foo { } # ... extending Quux::Foo class ::Baz { } # declares Baz</code></pre> <p>If you wish to use Moose or Mouse instead of Moo; include that in the declaration:</p> <pre><code>class Foo using Moose { # ... }</code></pre> <p>It's also possible to create classes <code>using Tiny</code> (<a href="/pod/Class::Tiny">Class::Tiny</a>), but there's probably little point in it, because Moops uses Moo internally, so the more capable Moo is already loaded and in memory.</p> <p>(The <code>using</code> option is exempt from the package qualification rules mentioned earlier.)</p> <p>Moops uses <a href="/pod/MooseX::MungeHas">MooseX::MungeHas</a> in your classes so that the <code>has</code> keyword supports some Moo-specific features, even when you're using Moose or Mouse. Specifically, it supports <code>is => 'rwp'</code>, <code>is => 'lazy'</code>, <code>builder => 1</code>, <code>clearer => 1</code>, <code>predicate => 1</code>, and <code>trigger => 1</code>. If you're using Moo, the <a href="/pod/MooX::late">MooX::late</a> extension is enabled too, which allows Moose-isms in Moo too. With the combination of these features, there should be very little difference between Moo, Mouse and Moose <code>has</code> keywords.</p> <p>Moops uses <a href="/pod/Lexical::Accessor">Lexical::Accessor</a> to provide you with private (lexical) attributes - that is, attributes accessed via a coderef method in a lexical variable.</p> <pre><code>class Foo { lexical_has foo => ( isa => Int, accessor => \(my $_foo), default => 0, ); method increment_foo () { $self->$_foo( 1 + $self->$_foo ); } method get_foo () { return $self->$_foo; } } my $x = Foo->new; $x->increment_foo(); # ok say $x->get_foo(); # says "1" $x->$_foo(42); # dies; $_foo does not exist in this scope</code></pre> <p>Moose classes are automatically accelerated using <a href="/pod/MooseX::XSAccessor">MooseX::XSAccessor</a> if it's installed.</p> <p>Note that it is possible to declare a class with an empty body; use a trailing semicolon.</p> <pre><code>class Employee extends Person with Employment;</code></pre> <p>If using Moose or Mouse, classes are automatically made immutable.</p> <p><a href="/pod/namespace::autoclean">namespace::autoclean</a> is automatically used in all classes.</p> <p>Between the class declaration and its body, <a href="/pod/Attribute::Handlers">Attribute::Handlers</a>-style attributes may be provided:</p> <pre><code>class Person :mutable { # ... } class Employee extends Person with Employment :mutable;</code></pre> <p>The following attributes are defined for classes:</p> <ul> <li><p><code>:assertions</code> - enables assertion checking (see below)</p> </li> <li><p><code>:dirty</code> - suppresses namespace::autoclean</p> </li> <li><p><code>:fp</code> - use <a href="/pod/Function::Parameters">Function::Parameters</a> instead of <a href="/pod/Kavorka">Kavorka</a></p> </li> <li><p><code>:mutable</code> - suppresses making Moose classes immutable</p> </li> <li><p><code>:ro</code> - make attributes declared with <code>has</code> default to 'ro'</p> </li> <li><p><code>:rw</code> - make attributes declared with <code>has</code> default to 'rw'</p> </li> <li><p><code>:rwp</code> - make attributes declared with <code>has</code> default to 'rwp'</p> </li> </ul> <h2 id="Roles">Roles</h2> <p>Roles can be declared similarly to classes, but using the <code>role</code> keyword.</p> <pre><code>role Stringable using Moose # we know you meant Moose::Role { # ... }</code></pre> <p>Roles do not support the <code>extends</code> option.</p> <p>Roles can be declared to be <code>using</code> Moo, Moose, Mouse or Tiny. (Note that if you're mixing and matching role frameworks, there are limitations to which class builders can consume which roles. Mouse is generally the least compatible; Moo and Moose classes should be able to consume each others' roles; Moo can also consume Role::Tiny roles.)</p> <p>If roles use Moo, the <a href="/pod/MooX::late">MooX::late</a> extension is enabled.</p> <p><a href="/pod/namespace::autoclean">namespace::autoclean</a> is automatically used in all roles.</p> <p>Roles take similar <a href="/pod/Attribute::Handlers">Attribute::Handlers</a>-style attributes to classes, but don't support <code>:mutable</code>.</p> <h3 id="A-note-on-consuming-roles"><a id="A"></a>A note on consuming roles</h3> <p>In a standard:</p> <pre><code>class MyClass with MyRole { ...; }</code></pre> <p>You should note that role composition is delayed to happen at the <i>end</i> of the class declaration. This is usually what you want.</p> <p>However the interaction between method modifiers and roles is complex, and <i>sometimes</i> you'll want the role to be applied to the class part-way through the declaration. In this case you can use a <code>with</code> statement <i>inside</i> the class declaration:</p> <pre><code>class MyClass { ...; with "MyRole"; ...; }</code></pre> <h2 id="Namespaces">Namespaces</h2> <p>The <code>namespace</code> keyword works as above, but declares a package without any class-specific or role-specific semantics.</p> <pre><code>namespace Utils { # ... }</code></pre> <p><a href="/pod/namespace::autoclean">namespace::autoclean</a> is not automatically used in namespaces.</p> <p><a href="/pod/Attribute::Handlers">Attribute::Handlers</a>-style attributes are supported for namespaces, but most of the built-in attributes make any sense without class/role semantics. (<code>:assertions</code> does.) Traits written as Moops extensions may support namespaces.</p> <h2 id="Functions-and-Methods"><a id="Functions"></a>Functions and Methods</h2> <p>Moops uses <a href="/pod/Kavorka">Kavorka</a> to declare functions and methods within classes and roles. Kavorka provides the <code>fun</code> and <code>method</code> keywords.</p> <pre><code>class Person { use Scalar::Util 'refaddr'; has name => (is => 'rwp'); # Moo attribute method change_name ( Str $newname ) { $self->_set_name( $newname ) unless $newname eq 'Princess Consuela Banana-Hammock'; } fun is_same_as ( Object $x, Object $y ) { refaddr($x) == refaddr($y) } } my $phoebe = Person->new(name => 'Phoebe'); my $ursula = Person->new(name => 'Ursula'); Person::is_same_as($phoebe, $ursula); # false</code></pre> <p>Note function signatures use type constraints from <a href="/pod/Types::Standard">Types::Standard</a>; <a href="/pod/MooseX::Types">MooseX::Types</a> and <a href="/pod/MouseX::Types">MouseX::Types</a> type constraints should also work, <i>provided you use their full names, including their package</i>.</p> <p>The <code>is_same_as</code> function above could have been written as a class method like this:</p> <pre><code>class Person { # ... method is_same_as ( $class: Object $x, Object $y ) { refaddr($x) == refaddr($y) } } # ... Person->is_same_as($phoebe, $ursula); # false</code></pre> <p>The <code>method</code> keyword is not provided within packages declared using <code>namespace</code>; only within classes and roles.</p> <p>See also <a href="/pod/Kavorka::Manual::Methods">Kavorka::Manual::Methods</a> and <a href="/pod/Kavorka::Manual::Functions">Kavorka::Manual::Functions</a>.</p> <p>Within Moose classes and roles, the <a href="/pod/MooseX::KavorkaInfo">MooseX::KavorkaInfo</a> module is loaded, to allow access to method signatures via the meta object protocol. (This is currently broken for <code>around</code> method modifiers.)</p> <p>In Moops prior to 0.025, <a href="/pod/Function::Parameters">Function::Parameters</a> was used instead of Kavorka. If you wish to continue to use Function::Parameters in a class you can use the <code>:fp</code> attribute:</p> <pre><code>class Person :fp { ...; }</code></pre> <p>Or to do so for all classes in a lexical scope:</p> <pre><code>use Moops function_parameters_everywhere => 1; class Person { ...; }</code></pre> <p>Or the environment variable <code>MOOPS_FUNCTION_PARAMETERS_EVERYWHERE</code> can be set to true to enable it globally, but this feature is likely to be removed eventually.</p> <h2 id="Method-Modifiers"><a id="Method"></a>Method Modifiers</h2> <p>Within classes and roles, <code>before</code>, <code>after</code> and <code>around</code> keywords are provided for declaring method modifiers. These use the same syntax as <code>method</code>.</p> <p>If your class or role is using Moose or Mouse, then you also get <code>augment</code> and <code>override</code> keywords.</p> <p>See also <a href="/pod/Kavorka::Manual::MethodModifiers">Kavorka::Manual::MethodModifiers</a>.</p> <h2 id="Multi-Methods"><a id="Multi"></a>Multi Methods</h2> <p><a href="/pod/Moops">Moops</a> uses <a href="/pod/Kavorka">Kavorka</a> to implement multi subs and multi methods.</p> <p>See also <a href="/pod/Kavorka::Manual::MultiSubs">Kavorka::Manual::MultiSubs</a>.</p> <h2 id="Type-Constraints"><a id="Type"></a>Type Constraints</h2> <p>The <a href="/pod/Types::Standard">Types::Standard</a> type constraints are exported to each package declared using Moops. This allows the standard type constraints to be used as barewords.</p> <p>Type constraints can be used in attribute definitions (<code>isa</code>) and method signatures. Because Types::Standard is based on <a href="/pod/Type::Tiny">Type::Tiny</a>, the same type constraints may be used whether you build your classes and roles with Moo, Moose our Mouse.</p> <p>Alternative libraries can be imported using the <code>types</code> option; a la:</p> <pre><code>class Document types Types::XSD::Lite { has title => (is => 'rw', isa => NormalizedString); }</code></pre> <p>Note that if an alternative type constraint library is imported, then <a href="/pod/Types::Standard">Types::Standard</a> is <i>not</i> automatically loaded, and needs to be listed explicitly:</p> <pre><code>class Document types Types::Standard, Types::XSD::Lite { # ... }</code></pre> <p>Type libraries built with <a href="/pod/Type::Library">Type::Library</a>, <a href="/pod/MooseX::Types">MooseX::Types</a> and <a href="/pod/MouseX::Types">MouseX::Types</a> should all work.</p> <p>Bear in mind that type constraints from, say, a <a href="/pod/MooseX::Types">MooseX::Types</a> library won't be usable in, say, Moo attribute definitions. However, it's possible to wrap them with Type::Tiny, and make them usable:</p> <pre><code>class Foo types MooseX::Types::Common::Numeric using Moo { use Types::TypeTiny qw( to_TypeTiny ); has favourite_number => ( is => 'rwp', isa => to_TypeTiny(PositiveInt) ); }</code></pre> <h2 id="Type-Libraries"><a id="Type1"></a>Type Libraries</h2> <p>You can use the <code>library</code> keyword to declare a new type library:</p> <pre><code>library MyTypes extends Types::Standard declares EmptyString, NonEmptyString { declare EmptyString, as Str, where { length($_) == 0 }; declare NonEmptyString, as Str, where { length($_) > 0 }; } class StringChecker types MyTypes { method check ( Str $foo ) { return "empty" if EmptyString->check($foo); return "non-empty" if NonEmptyString->check($foo); return "impossible?!"; } }</code></pre> <p>Libraries declared this way can extend existing type libraries written with <a href="/pod/Type::Library">Type::Library</a>, <a href="/pod/MooseX::Types">MooseX::Types</a> or <a href="/pod/MouseX::Types">MouseX::Types</a>.</p> <p>Note that this also provides a solution to the previously mentioned problem of using <a href="/pod/MooseX::Types">MooseX::Types</a> type libraries in <a href="/pod/Moo">Moo</a> classes:</p> <pre><code>library MyWrapper extends MooseX::Types::Common::Numeric; class Foo types MyWrapper using Moo { has favourite_number => ( is => 'rwp', isa => PositiveInt, ); }</code></pre> <h2 id="Constants">Constants</h2> <p>The useful constants <code>true</code> and <code>false</code> are imported into all declared packages. (Within classes and roles, namespace::autoclean will later remove them from the symbol table, so they don't form part of your package's API.) These constants can help make attribute declarations more readable.</p> <pre><code>has name => (is => 'ro', isa => Str, required => true);</code></pre> <p>Further constants can be declared using the <code>define</code> keyword (see <a href="/pod/PerlX::Define">PerlX::Define</a>):</p> <pre><code>namespace Maths { define PI = 3.2; }</code></pre> <p>Constants declared this way will <i>not</i> be swept away by namespace::autoclean, and are considered part of your package's API.</p> <h2 id="Assertions">Assertions</h2> <p>Declared packages can contain assertions (see <a href="/pod/PerlX::Assert">PerlX::Assert</a>). These are normally optimized away at compile time, but you can force them to be checked using the <code>:assertions</code> attribute.</p> <pre><code>class Foo { assert(false); # not checked; optimized away } class Bar :assertions { assert(false); # checked; fails; throws exception }</code></pre> <h2 id="More-Sugar"><a id="More"></a>More Sugar</h2> <p><a href="/pod/strict">strict</a> and FATAL <a href="/pod/warnings">warnings</a> are imported into all declared packages. However the <code>uninitialized</code>, <code>void</code>, <code>once</code> and <code>numeric</code> warning categories are explicitly excluded, as are any warnings categories added to Perl after version 5.14.</p> <p>Perl 5.14 features, including the <code>state</code> and <code>say</code> keywords, and sane Unicode string handling are imported into all declared packages.</p> <p><a href="/pod/Try::Tiny">Try::Tiny</a> is imported into all declared packages.</p> <p><a href="/pod/Scalar::Util">Scalar::Util</a>'s <code>blessed</code> and <a href="/pod/Carp">Carp</a>'s <code>confess</code> are imported into all declared packages.</p> <h2 id="Outer-Sugar"><a id="Outer"></a>Outer Sugar</h2> <p>The "outer" package, where the <code>use Moops</code> statement appears also gets a little sugar: strict, the same warnings as "inner" packages, and Perl 5.14 features are all switched on.</p> <p><a href="/pod/true">true</a> is loaded, so you don't need to do this at the end of your file:</p> <pre><code>1;</code></pre> <h2 id="Custom-Sugar"><a id="Custom"></a>Custom Sugar</h2> <p>It is possible to inject other functions into all inner packages using:</p> <pre><code>use Moops imports => [ 'List::Util' => [qw( first reduce )], 'List::MoreUtils' => [qw( any all none )], ];</code></pre> <p>This is by far the easiest way to extend Moops with project-specific extras.</p> <p>There is a shortcut for injecting <a href="/pod/strictures">strictures</a> into all inner packages:</p> <pre><code>use Moops -strict;</code></pre> <h1 id="EXTENDING">EXTENDING</h1> <p>Moops is written to hopefully be fairly extensible.</p> <h2 id="Extending-Moops-via-imports"><a id="Extending"></a>Extending Moops via imports</h2> <p>The easiest way to extend Moops is to inject additional imports into the inner packages using the technique outlined in <a href="#Custom-Sugar">"Custom Sugar"</a> above. You can wrap all that up in a module:</p> <pre><code>package MoopsX::Lists; use base 'Moops'; use List::Util (); use List::MoreUtils (); sub import { my ($class, %opts) = @_; push @{ $opts{imports} ||= [] }, ( 'List::Util' => [qw( first reduce )], 'List::MoreUtils' => [qw( any all none )], ); $class->SUPER::import(%opts); } 1;</code></pre> <p>Now people can do <code>use MoopsX::Lists</code> instead of <code>use Moops</code>.</p> <h2 id="Extending-Moops-via-keyword-traits"><a id="Extending1"></a>Extending Moops via keyword traits</h2> <p>Roles in the <code>Moops::TraitFor::Keyword</code> namespace are automatically loaded and applied to keyword objects when a corresponding Attribute::Handlers-style attribute is seen.</p> <p>For examples extending Moops this way, see the <a href="/pod/Moops::TraitFor::Keyword::dirty">Moops::TraitFor::Keyword::dirty</a>, <a href="/pod/Moops::TraitFor::Keyword::mutable">Moops::TraitFor::Keyword::mutable</a>, <a href="/pod/Moops::TraitFor::Keyword::ro">Moops::TraitFor::Keyword::ro</a>, <a href="/pod/Moops::TraitFor::Keyword::rw">Moops::TraitFor::Keyword::rw</a> and <a href="/pod/Moops::TraitFor::Keyword::rwp">Moops::TraitFor::Keyword::rwp</a> traits.</p> <h2 id="Extending-Moops-via-parser-traits"><a id="Extending2"></a>Extending Moops via parser traits</h2> <p>For more complex needs, you can create a trait which will be applied to Moops::Parser.</p> <p>Parser traits might want to override:</p> <ul> <li><p>The <code>keywords</code> class method, which returns the list of keywords the parser can handle.</p> </li> <li><p>The <code>class_for_keyword</code> object method, which returns the name of a subclass of Moops::Keyword which will be used for translating the result of parsing the keyword into a string using Perl's built-in syntax.</p> </li> </ul> <p>Hopefully you'll be able to avoid overriding the <code>parse</code> method itself, as it has a slightly messy API.</p> <p>Your <code>class_for_keyword</code> subclass can either be a direct subclass of Moops::Keyword, or of Moops::Keyword::Class or Moops::Keyword::Role.</p> <p>The keyword subclass might want to override:</p> <ul> <li><p>The <code>known_relationships</code> class method, which returns a list of valid inter-package relationships such as <code>extends</code> and <code>using</code> for the current keyword.</p> </li> <li><p>The <code>qualify_relationship</code> class method, which, when given the name of an inter-package relationship, indicates whether it should be subjected to package qualification rules (like <code>extends</code> and <code>with</code> are, but <code>using</code> is not).</p> </li> <li><p>The <code>version_relationship</code> class method, which, when given the name of an inter-package relationship, indicates whether it should accept a version number.</p> </li> <li><p>The <code>generate_package_setup</code> object method which returns a list of strings to inject into the package.</p> </li> <li><p>The <code>arguments_for_function_parameters</code> object method which is used by the default <code>generate_package_setup</code> method to set up the arguments to be passed to <a href="/pod/Function::Parameters">Function::Parameters</a>.</p> </li> <li><p>The <code>check_prerequisites</code> method which performs certain pre-flight checks and may throw an exception.</p> </li> </ul> <p>Hopefully you'll be able to avoid overriding the <code>generate_code</code> method.</p> <p>You can apply your trait using:</p> <pre><code>use Moops traits => [ 'Moops::TraitFor::Parser::FooKeyword', 'Moops::TraitFor::Parser::BarKeyword', ];</code></pre> <h1 id="BUGS">BUGS</h1> <p>If seeing test failures on threaded Perl 5.21+, it may be a bug in <a href="/pod/Devel::CallParser">Devel::CallParser</a> 0.002. Try installing <a href="/pod/Alt::Devel::CallParser::ButWorking">Alt::Devel::CallParser::ButWorking</a>.</p> <p>Please report any other bugs to <a href="http://rt.cpan.org/Dist/Display.html?Queue=Moops">http://rt.cpan.org/Dist/Display.html?Queue=Moops</a>.</p> <h1 id="GOTCHAS">GOTCHAS</h1> <p>Certain software (like the CPAN indexer!) greps Perl source code looking for <code>package</code> statements to determine which packages a module provides. Moops uses <code>class</code> and <code>role</code> keywords to declare packages, so it may be necessary to provide some dummy <code>package</code> statements at the end of your module if you need to support such software.</p> <h1 id="SUPPORT">SUPPORT</h1> <p><b>IRC:</b> support is available through in the <i>#moops</i> channel on <a href="http://www.irc.perl.org/channels.html">irc.perl.org</a>.</p> <p>For general Moose/Moo queries which don't seem to be related to Moops' syntactic sugar, your question may be answered more quickly in the <i>#moose</i> channel.</p> <p><b>Web:</b> if you ask a question on PerlMonks in <a href="http://www.perlmonks.org/?node_id=479">Seekers of Perl Wisdom</a> with "Moops" in the subject line, it should be answered pretty quickly.</p> <p>There is a <a href="http://stackoverflow.com/questions/tagged/moops">moops tag</a> on StackOverflow.</p> <h1 id="SEE-ALSO"><a id="SEE"></a>SEE ALSO</h1> <p>Similar: <a href="/pod/MooseX::Declare">MooseX::Declare</a>, <a href="https://github.com/stevan/p5-mop-redux">https://github.com/stevan/p5-mop-redux</a>.</p> <p>Main functionality exposed by this module: <a href="/pod/Moo">Moo</a>/<a href="/pod/MooX::late">MooX::late</a>, <a href="/pod/Kavorka">Kavorka</a>, <a href="/pod/Try::Tiny">Try::Tiny</a>, <a href="/pod/Types::Standard">Types::Standard</a>, <a href="/pod/namespace::autoclean">namespace::autoclean</a>, <a href="/pod/true">true</a>, <a href="/pod/PerlX::Assert">PerlX::Assert</a>.</p> <p>Internals fueled by: <a href="/pod/Keyword::Simple">Keyword::Simple</a>, <a href="/pod/Module::Runtime">Module::Runtime</a>, <a href="/pod/Import::Into">Import::Into</a>, <a href="/pod/Attribute::Handlers">Attribute::Handlers</a>.</p> <p><a href="http://en.wikipedia.org/wiki/The_Bubble_Boy_(Seinfeld)">http://en.wikipedia.org/wiki/The_Bubble_Boy_(Seinfeld)</a>.</p> <h1 id="AUTHOR">AUTHOR</h1> <p>Toby Inkster <tobyink@cpan.org>.</p> <h1 id="COPYRIGHT-AND-LICENCE"><a id="COPYRIGHT"></a>COPYRIGHT AND LICENCE</h1> <p>This software is copyright (c) 2013-2014 by Toby Inkster.</p> <p>This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.</p> <h1 id="DISCLAIMER-OF-WARRANTIES"><a id="DISCLAIMER"></a>DISCLAIMER OF WARRANTIES</h1> <p>THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.</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">×</button> <h4 class="modal-title">Module Install Instructions</h4> </div> <div class="modal-body"> <p>To install Moops, 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 Moops</code></pre> <p><a href="/pod/CPAN">CPAN shell</a></p> <pre><code>perl -MCPAN -e shell install Moops</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">×</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>