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

Are you sure you need this?

Looks like an exotic edge case for me ...

$var ||= "something else" is far more common.

... and Perl has already too many operators and changing the parser should be to complicated.

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^2: RFC: "assignary" operator ?= :
by richard.sharpe (Sexton) on Dec 07, 2019 at 16:34 UTC

    I wouldn't call it a need, just preference. I would like "exploiting" such feature this way:

    $var1 ?= die "ERROR: \$var1 already set." : $var2;

    Maybe you'll see more elegant way how to do such thing.

    Your suggestion with ||= is not ternary, just "binary", if I understand that correctly.

      > not ternary, just "binary",

      yes it's binary.

      > $var1 ?= die "ERROR: \$var1 already set." : $var2;

      Thanks for demonstrating your use case, it's even stranger than I expected! ;-)

      die will not return a value - actually it won't return at all.

      > Maybe you'll see more elegant way how to do such thing.

      Yes with a properly named custom-function operating on an alias.

      something like

      sub init { die "ERROR: \$var already set." if defined $_[0]; $_[0] = $_[1]; } init $var1 => 'value1'; # pretty elegant, right? init $var2 => 'value2'; init $var3 => 'value3';

      Please note the defined° , cause else wise you'd miss false values like 0 or "". (which renders your requirement for a new operator a bit useless)

      UPDATE:
      • if you need the proper $var name use PadWalker
      • use Carp to report from the perspective of the caller

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

      °) a shorter way would have been $_[0] // die 'ERROR: ...';

      Off by one, it's the inverted case :)

        Yes with a properly named custom-function operating on an alias.
        init $var1 => 'value1'; # pretty elegant, right?

        No, not at all. First, init() is a poor name which doesn't, by name, tell at all what it is doing. Second, the sub you wrote isn't at all ternary in any way, since it misses $_[2]. Third and last, function LIST doesn't tell at first glance that it is about conditional assignment to $_[0] from either $_[1] or $_[2] based on defined-ness of $_[0].

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

        Thank you, Rolf (and also other guys).

        Personally I'd prefer for such "basic thing" something "exactly explicit" just where it's used, without packaging/hiding it in the subroutine defined elsewhere. I prefer using custom subroutines for bit less simple logic (just personal preference).

        About no return from dying: yes, I really don't need returning from that death, therefore I called that "exploiting". But maybe somebody will find also other use cases for such "assignary" operator, not just this one.

        In the context of my practise (as used in my scripts and modules), I initialize (define) all my local variables just with heir my, to be more explict, what type of value are they predetermined to bear (number, string, hashref, etc.), e. g.:

        my $string = '';

        and therefore I don't need to differentiate undef from '', which means "not set" in my example.

        But, in case, of undefined variable used in assignary, e.g.:

        my $some_undefined_var; $some_undefined_var ?= die 'already set' : 'survived';

        on my opionion, it could stay alive, and "use of uninitialized value" warning raised on use warnings;.

      $var1 ?= die "ERROR: \$var1 already set." : $var2;

      would be far clearer as

      die "ERROR: \$var1 already set." if $var1; $var1 = $var2;

        Personally I feel this just obfuscates the problem at hand, but I dislike/hate statement-modifiers in general.

        $var1 and die "ERROR: ..."; $var1 = $var2;

        To **me** is extremely better readable (and thus maintanable) than your suggestion. TIMTOWTDI.


        Enjoy, Have FUN! H.Merijn

      This is a pretty cute alternative:

      sub empty ($) :lvalue { if ($_[0]) { require Carp; if (eval { require PadWalker }) { my $varname = PadWalker::var_name(1, \$_[0]); Carp::croak("$varname is not empty, stopped"); } Carp::croak("Variable is not empty, stopped"); } $_[0]; } # Asserts that $var1 is "empty" (i.e. the empty string, 0, or undef) a +nd assigns $var2 as the new value. empty $var1 = $var2; # Can also be used like this to assert $var1 is empty without assignin +g a new value. empty $var1;
        nice! :)

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