Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

printing unitialized value of the 'do BLOCK'

by rsFalse (Chaplain)
on Dec 17, 2019 at 14:47 UTC ( [id://11110281]=perlquestion: print w/replies, xml ) Need Help??

rsFalse has asked for the wisdom of the Perl Monks concerning the following question:

Hello again,

I was playing with 'do{ }' and found interesting behaviour. Here is a code:
#!/usr/bin/perl -l use strict; use warnings; my $uninitialized; print do { $uninitialized }; print do {}; print do { if( 1 ){} }; print do { if( 0 ){} }; print '-' x 10; print scalar do { $uninitialized }; print scalar do {}; print scalar do { if( 1 ){} }; print scalar do { if( 0 ){} };
output:
Use of uninitialized value $uninitialized in print at ./perlmonks_do_u +nitialized.pl line 8. 0 ---------- Use of uninitialized value $uninitialized in print at ./perlmonks_do_u +nitialized.pl line 15. Use of uninitialized value in print at ./perlmonks_do_unitialized.pl l +ine 16. Use of uninitialized value in print at ./perlmonks_do_unitialized.pl l +ine 17. 0
For me it is strange that 'scalar do {};' and 'scalar do { if( 0 ){} };' have different outputs, as the codes look equivalent. Can someone explain a difference in the output?

Replies are listed 'Best First'.
Re: printing unitialized value of the 'do BLOCK' (updated)
by haukex (Archbishop) on Dec 17, 2019 at 15:06 UTC
    For me it is strange that 'scalar do {};' and 'scalar do { if( 0 ){} };' have different outputs, as the codes look equivalent. Can someone explain a difference in the output?

    if (EXPR) BLOCK returns either the value of BLOCK, or that of EXPR if it is false. I am certain it's mentioned somewhere in passing in the Perl docs, but I'm having trouble finding it at the moment; I'll update when I do.

    Update: The text I was thinking of is in perlsub:

    If no return is found and if the last statement is an expression, its value is returned. If the last statement is a loop control structure like a foreach or a while, the returned value is unspecified. The empty sub returns the empty list.

    This "implicit return" stuff applies to do as well as to subs. As explained further down in this thread, in if (EXPR) BLOCK, when EXPR is false, the value of the last expression is that of EXPR, which is therefore returned.

      I already updated my post to say that you are probably right, but I'll say it again, straighter to the point: B::Deparse seems to confirm your interpretation as if (1) {BLOCK} is turned into do {BLOCK} (with BLOCK empty in rsFalse's example), and if (0) {} is turned into 0. So in the first case the if is optimized to return the value of the block, and in the second case the value of the EXPR.

      ++ to you obviously :)

        Fletch pointed out in the CB that using -x7 with B::Deparse gives the following confirmation:

        perl -MO=Deparse,-x7 -e "if ($a) { &BLOCK }" $a and do { &BLOCK }; -e syntax OK
        Where if (EXPR) {BLOCK} is equivalent to EXPR and do { BLOCK } which confirms haukex's interpretation. It's worth noting that if the two forms are equivalent, the latter is probably a lot less confusing when the output value is used.

        I remember this particular factoid because it has bothered me in the past that the return value of if isn't more clearly documented. I also know there was an old bug report in RT (not by me) to improve the docs that I'm having trouble finding right now as well :-/ I'm kind of busy right now so I'll report back on this later.

        Update: The issue I was thinking of is this one: perlsub should be more explicit when an implicit return encounters an if(){} statement, where davido suggests this text for perlsub instead:

        If no return is found and if the last statement is an expression, its value is returned. If the last statement is an if( CONDITION ) { BLOCK } construct, the value of the return value will come from BLOCK if CONDITION is true, or from CONDITION if CONDITION is false. Relying on this behavior is detremental to code legibility. If the last statement is a loop control structure like a foreach or a while, the returned value is unspecified.

        Fixed tpyo

Re: printing unitialized value of the 'do BLOCK'
by Eily (Monsignor) on Dec 17, 2019 at 15:11 UTC

    Edit: Because I couldn't find the documentation I expected the return value of an if block to be undefined behaviour, but Haukex's answer makes much more sense. You can ignore the rest of this post (except maybe the bit about Deparse, which actually confirms Haukex's version).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11110281]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2024-04-25 12:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found