Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re^2: RFC: "assignary" operator ?= :

by LanX (Saint)
on Dec 08, 2019 at 16:35 UTC ( [id://11109841]=note: print w/replies, xml ) Need Help??


in reply to Re: RFC: "assignary" operator ?= :
in thread RFC: "assignary" operator ?= :

What's the use case which justifies extending Perl's codebase for such an exotic feature?

I can hardly imagine a reason to map non-Boolean values to a previously Boolean $var without confusing any maintainer.

Using a new variable is always better then.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Replies are listed 'Best First'.
Re^3: RFC: "assignary" operator ?= :
by shmem (Chancellor) on Dec 08, 2019 at 17:37 UTC
    What's the use case which justifies extending Perl's codebase for such an exotic feature?

    Concise expressiveness. The ternary ? : is a shortcut for a more convoluted simple if/else

    my $var; if($cond) { $var = 'this'; } else { $var = 'that'; }

    to be written as

    my $var = $cond ? 'this' : 'that';

    which is one line compared to 5, 6 or 7, depending on indentation style.

    We have more of such subtle operators, eg. ||= vs. //=, where the first checks the LHS truthiness, and the second checks the LHS definedness.

    Writing

    $var = $var ? 'this' : 'that';

    just looks and feels as silly as

    $value = $value * 5; $next = $next + 1;

    instead of

    $value *= 5; $next++;

    For the same reasons, I like the compound operator x!! so much, because it lets me set up a parameter list based on truthiness of variables:

    $result = build_shed( logs => 24, (screws => 120) x!! @screwdrivers, (nails => 360) x!! @hammers, );

    Otherwise, I'd had to say:

    my %materials = (logs => 24); $materials{screws} = 120 if @screwdrivers; $materiasl{nails} = 360 if @hammers; $result = build_shed(%materials);

    While the second variant is one line less, I regard the first variant as much more readable, and I don't have to introduce a temporary hash just for the sake of building function arguments. Note that in the second variant, the hash name is misspelt as materiasl at the 'nails' case, small bug caught by strict, but annoying. So, instead of

    $var = $var ? 'this' : 'that';

    I'd rather like to see

    $var ?= 'this' : 'that';

    because it binds the condition to the LHS in the same way as ||= and //= do.

    I can hardly imagine a reason to map non-Boolean values to a previously Boolean $var without confusing any maintainer.

    Who said that $var was boolean? It could hold any value, and this value is checked for truthiness.

    Anyways - de gustibus non est disputandem.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      > I like the compound operator x!!

      It's a bit different than the if/else or ternary it's used to replace, though. Unlike them, the x!! evaluates the left hand side even if the condition is zero. Cf.

      my $t; sub tuple { $t++ => 12 } my $bool = 0; my %h = (tuple()) x !! $bool;
      versus
      ... my %h = $bool ? (tuple()) : ();

      Now %h is the same, but $t is different.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        It's a bit different than the if/else or ternary it's used to replace, though

        Ah no, this construct doesn't replace any ternary, it is a wholly different thing - but an example for replacement of a convoluted construct with a succinct idiom. Once you grok what x!! is about, you'll never forget what it does.

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      The semantics are already perfectly understood, but you haven't shown us a use case.

      Edit: When and why does this ever happen???

      > $var = $var ? 'this' : 'that';

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        When and why does this ever happen???

        As for why, I don't know. But it does. On this old debian box:

        qwurx [shmem] ~> libdirs=`perl -E 'say for @INC'` qwurx [shmem] ~> perl -lne 'print "$ARGV: $_" if /\$(\w+)\s+=\s+\$\1\s +*\?/' `(for d in $libdirs; do find $d -type f; done)` /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.pm: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.pm: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.pm: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.pm: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.yp: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.yp: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.yp: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/Treeregexp.yp: $semantic = +$semantic? $semantic->{attr} : undef; /usr/local/share/perl/5.20.2/Parse/Eyapp/eyapp: $opt_s = $opt_s ? 1 : +0; /usr/local/share/perl/5.20.2/Parse/Eyapp/eyapp: $opt_n = $opt_n ? 0 : +1; /usr/local/share/perl/5.20.2/Net/EmptyPort.pm: $proto = $proto ? l +c($proto) : 'tcp'; /usr/local/share/perl/5.20.2/Net/EmptyPort.pm: $proto = $proto ? l +c($proto) : 'tcp'; /usr/local/share/perl/5.20.2/Net/EmptyPort.pm: $proto = $proto ? l +c($proto) : 'tcp'; Can't open /usr/local/share/perl/5.20.2/.Inline.pm.swp: Permission den +ied at -e line 1, <> line 524147. /usr/local/share/perl/5.20.2/ExtUtils/ParseXS.pm: $externC = $exte +rnC ? qq[extern "C"] : ""; /usr/local/share/perl/5.20.2/Test/Builder/Tester.pm: $got = $g +ot ? "$got\n$g" : $g; /usr/local/share/perl/5.20.2/Test/Builder/Tester.pm: $wanted = + $wanted ? "$wanted\n$w" : $w; /usr/local/share/perl/5.20.2/Test/Builder.pm: $test = $test ? 1 : +0; /usr/local/share/perl/5.20.2/Test/Tester/Capture.pm: $test = $test + ? 1 : 0; /usr/local/share/perl/5.20.2/Test2/Compare/Bool.pm: $match = $matc +h ? 0 : 1 if $self->{+NEGATE}; /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Provider.pm: $parser + = $parser ? $parser->_dump() : '<no parser>'; /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Provider.pm: + $prev = $prev ? "#$lut->{ $prev }<-": '<undef>'; /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Provider.pm: + $next = $next ? "->#$lut->{ $next }": '<undef>'; /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Directive.pm: $line += $line ? " (starting line $line)" : ''; /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Directive.pm: $args += $args ? "$args, $alias" : ", undef, $alias" /usr/lib/x86_64-linux-gnu/perl5/5.20/DBI/SQL/Nano.pm: if ($neg) { +$match = $match ? 0 : 1; } /usr/share/perl5/SQL/Translator/Producer/Oracle.pm: $i +ndex_name = $index_name ? mk_name( $index_name ) /usr/share/perl5/SQL/Translator/Producer/Oracle.pm: $i +ndex_name = $index_name ? mk_name( $index_name ) /usr/share/perl5/SQL/Translator/Producer/Oracle.pm: $i +ndex_name = $index_name ? mk_name( $index_name ) /usr/share/perl5/SQL/Translator/Producer/Oracle.pm: $d +efault = $default ? "'1'" : "'0'"; /usr/share/perl5/SQL/Abstract.pm: $sql = $sql ? $self->_sqlcase(' wh +ere ') . "( $sql )" : ''; /usr/share/perl5/Parse/RecDescent.pm: $lookahead = $lookah +ead ? -$lookahead : -1; /usr/share/perl5/Parse/RecDescent.pm: $lookahead = $lookah +ead ? $lookahead : 1; /usr/share/perl5/HTTP/Cookies/Netscape.pm: $expires = $expires ? $ +expires - $HTTP::Cookies::EPOCH_OFFSET : 0; /usr/share/perl5/HTTP/Cookies/Netscape.pm: $secure = $secure ? "TR +UE" : "FALSE"; /usr/share/perl5/Config/Tiny.pm: $encoding = $encoding ? "<:$en +coding" : '<'; /usr/share/perl5/Config/Tiny.pm: $encoding = $encoding ? ">:$en +coding" : '>'; /usr/share/perl5/Mojo/DOM.pm: $start = $start ? ($#$tree + 1) : _s +tart($tree); /usr/share/perl5/Mojo/DOM.pm: $offset = $offset ? $#$tree : 0; /usr/share/perl5/Font/TTF/OldMort.pm: $_ = $_ +? $_ - ($mappingTables / 2) : undef; /usr/share/perl5/Font/TTF/Mort/Contextual.pm: $_ = $_ ? $_ + - ($mappingTables / 2) : undef; /usr/share/perl5/Net/EmptyPort.pm: $proto = $proto ? lc($proto +) : 'tcp'; /usr/share/perl5/Net/EmptyPort.pm: $proto = $proto ? lc($proto +) : 'tcp'; /usr/share/perl5/Net/SNMP/Transport/IPv6.pm: $s = $s ? sprintf('%%% +u', $s) : q{}; /usr/share/perl5/Net/SNMP/Transport/IPv6.pm: $s = $s ? pack('N', $s +) : q{}; /usr/share/perl5/UNIVERSAL/isa.pm: $extra = $extra ? " ($extra)" : + ''; /usr/share/perl5/IO/Socket/Socks.pm: $status = $status ? AUTHREPLY +_SUCCESS : 1; #XXX AUTHREPLY_FAILURE broken /usr/share/perl5/Text/CSV_PP.pm: $v =~ m/^[0-9]/ or $v = $v ? +1 : 0; # default for true/false /usr/share/perl5/Text/CSV_PP.pm: $v =~ m/^[0-9]/ or $v = $v ? +1 : 0; # default for true/false /usr/share/perl5/Lintian/Tags.pm: $found = $found +? 0 : 1; /usr/share/perl5/Excel/Writer/XLSX/Drawing.pm: $underline = $under +line ? 'sng' : 'none'; /usr/share/perl5/Excel/Writer/XLSX/Drawing.pm: $strike = $strike ? + 'Strike' : 'noStrike'; /usr/share/perl5/Test/Toolbox.pm: $is = $is ? 'true' : 'false'; /usr/share/perl5/Test/Toolbox.pm: $should = $should ? 'true' : 'fa +lse'; /usr/share/perl5/Test/Toolbox.pm: $ok = $ok ? 1 : 0; /usr/share/perl5/Spreadsheet/WriteExcel/Worksheet.pm: $visible + = $visible ? 0x0000 : 0x0002; /usr/share/perl5/Spreadsheet/WriteExcel/Worksheet.pm: $visible + = $visible ? 0x0002 : 0x0000; /usr/share/perl5/Spreadsheet/ParseExcel/Utility.pm: $doubl +e_quote = $double_quote ? 0 : 1; /usr/share/perl5/Spreadsheet/XLSX/Utility2007.pm: $iDblQ = + $iDblQ? 0: 1; /usr/share/perl5/Zoidberg/StringParser.pm: $expr = $ex +pr ? '('.$expr.')|' : ''; /usr/share/perl5/Image/ExifTool/QuickTime.pm: $lang = $lang ? +"($lang) " : ''; /usr/share/perl5/Image/ExifTool/QuickTime.pm: $lang = $lan +g ? "($lang) " : ''; /usr/share/perl5/Image/ExifTool/QuickTime.pm: $lang = $lan +g ? "($lang) " : ''; /usr/share/perl5/Image/ExifTool/QuickTime.pm: $lang = $lan +g ? "($lang) " : ''; /usr/share/perl5/Image/ExifTool/QuickTime.pm: $lang = $lan +g ? "($lang) " : ''; /usr/share/perl5/Image/ExifTool/XMPStruct.pl: $delim = $delim +? "\\$delim|,|\\||\$" : ',|\\||$'; /usr/share/perl5/Image/ExifTool/BuildTagLookup.pm: $rowCla +ss = $rowClass ? '' : " class=b"; /usr/share/perl5/Image/ExifTool/ASF.pm: $_ = $_ ? 'True' : + 'False'; /usr/share/perl5/Image/ExifTool.pm: $tagInfo = $tagInfo ? { Name = +> $tagInfo } : { } unless ref $tagInfo eq 'HASH'; /usr/share/perl5/Type/Params.pm: $constraint = $constraint + ? Any : Optional[Any]; /usr/share/perl5/CGI/Compile.pm: $proto = $proto ? "($proto)" : '' +; /usr/share/perl5/assert.pl: $w = $w ? '@ = ' : '$ = '; /usr/share/perl5/IPC/Run.pm: $r = $r ? '' : " ERROR $!"; /usr/share/perl5/IPC/Run.pm: $out = $out ? 'b' : 'w' + if vec( $self->{WIN}, $_, 1 ); /usr/share/perl5/IPC/Run.pm: $out = $out ? uc( $out ) : + 'x' if vec( $self->{EIN}, $_, 1 ); /usr/share/perl5/IPC/Run.pm: $out = $out ? 'b' : 'w' + if vec( $self->{WOUT}, $_, 1 ); /usr/share/perl5/IPC/Run.pm: $out = $out ? uc( $out ) : + 'x' if vec( $self->{EOUT}, $_, 1 ); /usr/share/perl5/AppConfig/State.pm: $value = $value ? 0 : 1 i +f $negate; ./SQL/Translator/Producer/Oracle.pm: $index_name = $in +dex_name ? mk_name( $index_name ) ./SQL/Translator/Producer/Oracle.pm: $index_name = $in +dex_name ? mk_name( $index_name ) ./SQL/Translator/Producer/Oracle.pm: $index_name = $in +dex_name ? mk_name( $index_name ) ./SQL/Translator/Producer/Oracle.pm: $default = $defau +lt ? "'1'" : "'0'"; ./SQL/Abstract.pm: $sql = $sql ? $self->_sqlcase(' where ') . "( $sq +l )" : ''; ./Parse/RecDescent.pm: $lookahead = $lookahead ? -$lookahe +ad : -1; ./Parse/RecDescent.pm: $lookahead = $lookahead ? $lookahea +d : 1; ./HTTP/Cookies/Netscape.pm: $expires = $expires ? $expires - $HTTP +::Cookies::EPOCH_OFFSET : 0; ./HTTP/Cookies/Netscape.pm: $secure = $secure ? "TRUE" : "FALSE"; ./Config/Tiny.pm: $encoding = $encoding ? "<:$encoding" : '<'; ./Config/Tiny.pm: $encoding = $encoding ? ">:$encoding" : '>'; ./Mojo/DOM.pm: $start = $start ? ($#$tree + 1) : _start($tree); ./Mojo/DOM.pm: $offset = $offset ? $#$tree : 0; ./Font/TTF/OldMort.pm: $_ = $_ ? $_ - ($mappin +gTables / 2) : undef; ./Font/TTF/Mort/Contextual.pm: $_ = $_ ? $_ - ($mappingTab +les / 2) : undef; ./Net/EmptyPort.pm: $proto = $proto ? lc($proto) : 'tcp'; ./Net/EmptyPort.pm: $proto = $proto ? lc($proto) : 'tcp'; ./Net/SNMP/Transport/IPv6.pm: $s = $s ? sprintf('%%%u', $s) : q{}; ./Net/SNMP/Transport/IPv6.pm: $s = $s ? pack('N', $s) : q{}; ./UNIVERSAL/isa.pm: $extra = $extra ? " ($extra)" : ''; ./IO/Socket/Socks.pm: $status = $status ? AUTHREPLY_SUCCESS : 1; # +XXX AUTHREPLY_FAILURE broken ./Text/CSV_PP.pm: $v =~ m/^[0-9]/ or $v = $v ? 1 : 0; # defaul +t for true/false ./Text/CSV_PP.pm: $v =~ m/^[0-9]/ or $v = $v ? 1 : 0; # defaul +t for true/false ./Lintian/Tags.pm: $found = $found ? 0 : 1; ./Excel/Writer/XLSX/Drawing.pm: $underline = $underline ? 'sng' : +'none'; ./Excel/Writer/XLSX/Drawing.pm: $strike = $strike ? 'Strike' : 'no +Strike'; ./Test/Toolbox.pm: $is = $is ? 'true' : 'false'; ./Test/Toolbox.pm: $should = $should ? 'true' : 'false'; ./Test/Toolbox.pm: $ok = $ok ? 1 : 0; ./Spreadsheet/WriteExcel/Worksheet.pm: $visible = $visible + ? 0x0000 : 0x0002; ./Spreadsheet/WriteExcel/Worksheet.pm: $visible = $visible + ? 0x0002 : 0x0000; ./Spreadsheet/ParseExcel/Utility.pm: $double_quote = $doub +le_quote ? 0 : 1; ./Spreadsheet/XLSX/Utility2007.pm: $iDblQ = $iDblQ? 0: 1; ./Zoidberg/StringParser.pm: $expr = $expr ? '('.$expr. +')|' : ''; ./Image/ExifTool/QuickTime.pm: $lang = $lang ? "($lang) " : '' +; ./Image/ExifTool/QuickTime.pm: $lang = $lang ? "($lang) " +: ''; ./Image/ExifTool/QuickTime.pm: $lang = $lang ? "($lang) " +: ''; ./Image/ExifTool/QuickTime.pm: $lang = $lang ? "($lang) " +: ''; ./Image/ExifTool/QuickTime.pm: $lang = $lang ? "($lang) " +: ''; ./Image/ExifTool/XMPStruct.pl: $delim = $delim ? "\\$delim|,|\ +\||\$" : ',|\\||$'; ./Image/ExifTool/BuildTagLookup.pm: $rowClass = $rowClass +? '' : " class=b"; ./Image/ExifTool/ASF.pm: $_ = $_ ? 'True' : 'False'; ./Image/ExifTool.pm: $tagInfo = $tagInfo ? { Name => $tagInfo } : +{ } unless ref $tagInfo eq 'HASH'; ./Type/Params.pm: $constraint = $constraint ? Any : Option +al[Any]; ./CGI/Compile.pm: $proto = $proto ? "($proto)" : ''; ./assert.pl: $w = $w ? '@ = ' : '$ = '; ./IPC/Run.pm: $r = $r ? '' : " ERROR $!"; ./IPC/Run.pm: $out = $out ? 'b' : 'w' if vec( $s +elf->{WIN}, $_, 1 ); ./IPC/Run.pm: $out = $out ? uc( $out ) : 'x' if vec( $s +elf->{EIN}, $_, 1 ); ./IPC/Run.pm: $out = $out ? 'b' : 'w' if vec( $s +elf->{WOUT}, $_, 1 ); ./IPC/Run.pm: $out = $out ? uc( $out ) : 'x' if vec( $s +elf->{EOUT}, $_, 1 ); ./AppConfig/State.pm: $value = $value ? 0 : 1 if $negate;

        So, it looks like there are plenty of use cases ;)

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11109841]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-04-23 23:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found