Re: RFC: "assignary" operator ?= :
by LanX (Saint) on Dec 07, 2019 at 16:13 UTC
|
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.
| [reply] [d/l] |
|
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.
| [reply] [d/l] [select] |
|
> 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
°) a shorter way would have been $_[0] // die 'ERROR: ...';
Off by one, it's the inverted case :) | [reply] [d/l] [select] |
|
|
|
|
$var1 ?= die "ERROR: \$var1 already set." : $var2;
would be far clearer as
die "ERROR: \$var1 already set." if $var1;
$var1 = $var2;
| [reply] [d/l] [select] |
|
|
|
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;
| [reply] [d/l] |
|
Re: RFC: "assignary" operator ?= :
by shmem (Chancellor) on Dec 07, 2019 at 22:25 UTC
|
I like it. Very much. Looks to me like a very concise and logical addition to operators modifying the LHS, like *= /= ||= and such. And it is readable, fluently!
$var ?= "something" : "something else";
"If $var is set, assign to it 'something', else 'something else'"
"Elegant as f*ck", as a cow-orker coined a python expression.
I'd really like to have that operator added. If I find the time (and brainz) to whip up a proposal with patches, I'll do. Hopefully.
Thanks!
perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
| [reply] [d/l] [select] |
|
| [reply] |
|
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'
| [reply] [d/l] [select] |
|
|
|
|
|
Re: RFC: "assignary" operator ?= :
by tobyink (Canon) on Dec 08, 2019 at 21:47 UTC
|
You can think of it as an "upgrading" operation for a boolean variable.
Like if a variable contains a Perl boolean, you can upgrade it to a JSON boolean:
$var ?= JSON::PP::true : JSON::PP::false;
Or you can upgrade a Perl boolean to some HTML:
my $is_ready = 1;
$is_ready = 0 if $service->not_configured();
$is_ready = 0 if $service->payment->status() ne 'paid';
$is_ready ?= '<span class="green">yes</span>' : '<span class="red">no<
+/span>';
print "<p>Service ready? $is_ready</p>";
| [reply] [d/l] [select] |
|
my $is_ready = 1;
$is_ready = 0 if $service->not_configured();
$is_ready = 0 if $service->payment->status() ne 'paid';
$is_ready
or print "<p>Service ready? <span class="red">no</span></p>";
$is_ready
and print gettext('yes ready');
| [reply] [d/l] |
Re: RFC: "assignary" operator ?= :
by kcott (Archbishop) on Dec 09, 2019 at 05:53 UTC
|
$var = ("something else", "something")[!!$var];
Some examples:
$ perl -E 'my $x; $x = (0,1)[!!$x]; say $x'
0
$ perl -E 'my $x = ""; $x = (0,1)[!!$x]; say $x'
0
$ perl -E 'my $x = "X"; $x = (0,1)[!!$x]; say $x'
1
From "Re^2: RFC: "assignary" operator ?= :":
$var1 ?= die "ERROR: \$var1 already set." : $var2;
You could do something rather exotic like:
$ perl -E 'my $x = ""; $x = (42, $x && die "Set: $x")[!!$x]; say $x'
42
$ perl -E 'my $x = "X"; $x = (42, $x && die "Set: $x")[!!$x]; say $x'
Set: X at -e line 1.
But ask yourself:
-
Do you fully understand what's happening with that code?
-
Will the next maintainer fully understand what's happening with that code?
-
Wouldn't a simple if/else block be easier to write, read, understand and maintain?
| [reply] [d/l] [select] |
|
$var is repeated thus missing the point
| [reply] |
Re: RFC: "assignary" operator ?= : ( conditional assignment , golf, death by diabetes )
by Anonymous Monk on Dec 09, 2019 at 02:13 UTC
|
New operators jerk my knee jerk
But they come and they go
but it they come they must come correct in perlop, no half assing like Postfix Dereference
assignary ? No
Its conditional assignment
Also not ter-signment , tri-sign, con-sign
$var = $var ? JSON::PP::true : JSON::PP::false;
$var ?= JSON::PP::true : JSON::PP::false;
$var = $var
? JSON::PP::true
: JSON::PP::false;
$var ?= JSON::PP::true
: JSON::PP::false;
($coo ?= $fudge : $brownie ) ?= $blondie : $oatmeal;
($coo ?= $fudge
: $brownie ) ?= $blondie : $oatmeal;
($coo ?= $fudge
: $brownie ) ?= $blondie
: $oatmeal;
($coo ?= $fudge
: $brownie
) ?= $blondie
: $oatmeal;
$coo = $coo
? $fudge
: $brownie;
$coo = $coo
? $blondie
: $oatmeal;
diabetes, a pleasant way to die? | [reply] [d/l] |
|
| [reply] |
|
| [reply] |
|
Re: RFC: "assignary" operator ?= : ( source Filter::PPI::Transform )
by Anonymous Monk on Dec 11, 2019 at 06:29 UTC
|
PPI::Document
PPI::Statement
PPI::Token::Symbol '$foo'
PPI::Token::Whitespace ' '
PPI::Token::Operator '?' ##################
PPI::Token::Operator '=' ##################
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$bar'
PPI::Token::Whitespace ' '
PPI::Token::Operator ':' ##################
PPI::Token::Whitespace ' '
PPI::Token::Symbol '$baz'
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
PPI::Statement
PPI::Token::Symbol '$foo'
PPI::Token::Whitespace ' '
PPI::Token::Operator '?' ##################
PPI::Token::Operator '=' ##################
PPI::Token::Whitespace ' '
PPI::Structure::List ( ... )
PPI::Token::Whitespace ' '
PPI::Statement::Expression
PPI::Token::Word 'rand'
PPI::Structure::List ( ... )
PPI::Token::Whitespace ' '
PPI::Token::Whitespace ' '
PPI::Token::Operator ':' ##################
PPI::Token::Whitespace ' '
PPI::Structure::List ( ... )
PPI::Token::Whitespace ' '
PPI::Statement::Expression
PPI::Token::Symbol '$baz'
PPI::Token::Whitespace ' '
PPI::Token::Structure ';'
PPI::Token::Whitespace '\n'
Filter::PPI::Transform - Tiny adapter module from PPI::Transform to source filter
PPI::Transform
PPI::Transform::UpdateCopyright - Demonstration PPI::Transform class
PPI-Transform-Sequence-v0.0.3
Tiny binder to combine multiple PPI::Transform objects 12 Nov 2012 13:43:39 GMT
Perl-Squish-1.06
Reduce Perl code to a few characters as possible 08 Apr 2009 11:07:41 GMT | [reply] [d/l] |
|
| [reply] |
|
| [reply] |
|
|
#!/usr/bin/perl --
BEGIN{
package PPI::Transform::ConditionalAssignment;
use strict;
use warnings;
use Params::Util qw{_STRING _INSTANCE};
use PPI::Transform ();
use parent 'PPI::Transform';
our $VERSION = '0.1'; # VERSION
sub document {
my $self = shift;
my $document = _INSTANCE(shift, 'PPI::Document') or return undef;
my $elements = $document->find( sub {
$_[1]->isa('PPI::Token::Operator') or return '';
$_[1]->content eq '?' or return '';
$_[1]->snext_sibling->isa('PPI::Token::Operator') or return ''
+;
$_[1]->snext_sibling->content eq '=' or return '';
return 1;
} );
return undef unless defined $elements;
return 0 unless $elements;
my $changes = 0;
foreach my $question ( @$elements ) {
my $symbol = $question->sprevious_sibling->clone;
my $equals = $question->snext_sibling;
$equals->insert_after( $symbol );
$symbol->insert_after( $question->remove );
$changes++;
}
return $changes;
}
1;
$INC{'PPI/Transform/ConditionalAssignment.pm'}=__FILE__;
} # BEGIN
package main;
use Filter::PPI::Transform 'PPI::Transform::ConditionalAssignment';
for my $foo ( 0 .. 1 ) {
my $bar = $foo;
$foo ?= 'one' : 'zero';
print "$foo\n";
$bar ?= ('one '.rand): ('zero '.rand);
print "$bar\n";
}
print "let me know " ? "should I stay" : "or should I go";
__END__
$ perl ppi-transform-conditional-assignment.pl
zero
zero 0.563323974609375
one
one 0.086761474609375
should I stay
| [reply] [d/l] |
Re: RFC: "assignary" operator ?= :
by Anonymous Monk on Dec 10, 2019 at 03:57 UTC
|
Please. We no longer live in a world where we need to save bytes or keystrokes. Don't muddy the water just because you can. | [reply] |
|
From my point of view, it's not just about bytes or keystrokes, but about command verbalization efficiency and (subjective, of course) elegance. When I command somebody, I don't want to say it twice :). Perl gives you a lot of freedom of choices, allows a lot of "artism", for example in comparison with Python, which is more rigid. And this suggestion is about further development of this Perl's unique nature. Tim Toady likes it.
| [reply] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|