简体   繁体   中英

Why doesn't `my $x = if (0) {1} else {2}` work?

In perl, $x = if (0) {1} else {2} does not work.

$ perl -E'$x = if (0) {1} else {2}'
syntax error at -e line 1, near "= if"
Execution of -e aborted due to compilation errors.

This makes sense, because if conditionals are not expressions in Perl. They're flow control.

But then

my $x = do { if (0) {1} else {2} };

Does work! How come a do BLOCK can accept an if conditional? But assignment can not? It would seem in the above the flow control must either

  • know it's context in a do BLOCK
  • always act as an expression, but have that syntax disallowed by the parser.

Moreover given the simple facts above, what is the right way to describe an if-conditional that behaves like that? Is it an expression with a value? Is it flow-control construct that has no value after evaluation?

And, lastly, what modifications would have to be made to assignment to have it accept an if condition like a do BLOCK .

The only answer and commentary that addresses the question in a matter that brings clarity is Ginnz,

The over-arching design is that perl has keywords that only are meaningful in certain contexts, and if is one of them - it can be only the start of a statement or a statement modifier, and neither of those are valid directly after an = . This is a parser distinction first and foremost. Beyond that, the consideration of "what an if statement returns" is not always intuitive, so while you can find that out by putting it in a do block or the last statement of a subroutine, it's not something that should be encouraged to be used as a value. In fact it commonly leads to bugs . – Grinnz 11 hours ago

When Ginnz says parser distinction, I interpret that to mean that this isn't much worth pursing as a matter of clarity. What is valid after an = is simply not a if statement, and there is no real reason for it, except that it's how it is.

  • if conditional is a statement.
  • statement's return values.
  • assignment = expressly forbids statements on the right because it only accepts things in the expression class.
  • a do BLOCK can turn a statement into an expression.

Code inside DO block behaves differently. Perl interprets the code inside the curly brackets and outputs the result of the last command.


    #!/usr/bin/perl
    
    use Data::Dumper;
    
    my $x = do { { 1==1 } };
    my $y = do { { 1==0 } };
    print Dumper 1==0;
    print Dumper $x;
    print Dumper $y;

Read more about do: https://perldoc.perl.org/perlfunc#do

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM