Wise monks,
I have stumbled over a behavior that I cannot explain, and I am seeking your knowledge to help me understand better.

In the middle of editing and restructuring some code, I happened to have the initialization of a lexical variable at the beginning of a subroutine expressed like this:

my $my_var = "default" unless defined $param; $my_var //= $param;

Clearly, this could (and maybe should) be written much nicer as my $my_var = $param // "default"; but at that point I wanted to verify some other things and ran the above version.

When I called the subroutine several times for testing, with different parameters, I had results that seem strange to me.
The lexical variable, of which I thought it would be created as undef for each call to the subroutine, kept its value from one call to another if the condition for the initialization was false.

The following program shows what I mean:

#!/usr/bin/env perl use strict; use warnings; use feature 'say'; use feature 'signatures'; no warnings 'experimental::signatures'; use Data::Dump qw( pp ); sub foo( $param ) { say "\$param is ", pp( $param ); my $my_var = "default" unless defined $param; say "\$my_var after declaration is ", pp( $my_var ); say +( defined $param ? ! defined $my_var : defined $my_var && $my_var eq 'default' ) ? " (as expected)" : " (unexpected to me!)"; $my_var //= $param; say "\$my_var after '//=' is ", pp( $my_var ); say ""; return $my_var; } foo( $_ ) for undef, "call 1", "call 2", "call 3"; 1;
The output is:
$ ./my_with_if.pl $param is undef $my_var after declaration is "default" (as expected) $my_var after '//=' is "default" $param is "call 1" $my_var after declaration is undef (as expected) $my_var after '//=' is "call 1" $param is "call 2" $my_var after declaration is "call 1" (unexpected to me!) $my_var after '//=' is "call 1" $param is "call 3" $my_var after declaration is "call 1" (unexpected to me!) $my_var after '//=' is "call 1"

The point is that $my_var still contains the "call 1" value from the previous call in the "call 2" call.
Why isn't it undef?

I also find it interesting to see that $my_var *is* initialized to undef as I would expect in the "call 1" call, where the value from the call before was the "default" value. This means that the value is not *always* kept from the call before!
Very strange!

Did I find a bug in the conditional initialization of lexical (my) variables?
Or maybe it is just an unspecified (or 'undefined' :-)) behavior?
Which would explain that I didn't find any specific explanation in the Perldoc (Private Variables via my())?

Thank you for your help!

Matthias

In reply to Conditional initialization of lexical (my) variables by muthm

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.