Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: postfix syntax enlightenment

by Eily (Hermit)
on Mar 28, 2014 at 18:35 UTC ( #1080134=note: print w/ replies, xml ) Need Help??


in reply to postfix syntax enlightenment

The perlsyn doc on statment modifiers says that a line such as my $var = 1 if $test; leads to an undefined behaviour: you don't know what happens to the variable if the condition evaluates to false.

Anyway in your case, even if you had written my $var; $var = $params->{test} if exists $params->{test}, you would still have the same result, because unless $params->{test} exists, you don't put any value in $test1.

A simple way to do what you want is to write:

my $i = shift; my $params = shift; my $test1 = $i; # $test1 is $i by default $test1 = $params->{test} if exists $params->{test}; # change its value + when appropriate

You may be interested by the defined or operator (which would still lead to autovivification of the $params->{test} value in your case), and the ternary operator to solve problems similar to this one.


Comment on Re: postfix syntax enlightenment
Select or Download Code
Re^2: postfix syntax enlightenment
by Laurent_R (Parson) on Mar 28, 2014 at 19:53 UTC

    The perlsyn doc on statment modifiers says that a line such as my $var = 1 if $test; leads to an undefined behaviour: you don't know what happens to the variable if the condition evaluates to false.

    Are you sure of that? This is not what I understand from the document you quote. My understanding, from reading aforesaid document, is that my $var if $test; is undefined. But this is quite different. Please note that this is not a troll at all, I would really like to know. Although, in such a case, I would normally declare the variable and assign it in separate instructions, I think there might be some of my programs (at most very few) where I used something equivalent to my $var = 1 if $test; and I don't recall having encountered any problem with this type of syntax (but it is also quite possible that I actually never did it, I would in principle be suspicious with such a construct with conditional declaration).

    This seems to work according to my expectations:

    $ perl -e 'my $c = 1 if 1; print $c;' 1 ~ $ perl -e 'my $c = 1 if 0; print $c;'
      My understanding, from reading aforesaid document, is that my $var if $test; is undefined.

      But the cited doc in Re: postfix syntax enlightenment sez "NOTE: The behaviour of ... is undefined.", clearly, I think, referring to behavior (or behaviour, if you will) rather than to the state of the lexical being undef (if I correctly understand your understanding). (The link is to 5.18.2 docs, but my local 5.10.1 docs say essentially the same, but without reference to state or our.)

      The documentation that Eily references says this:

      NOTE: The behaviour of a my, state, or our modified with a statement modifier conditional or loop construct (for example, my $x if ...) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.

      The example it gives is:

      my $x if ...

      The example you give is:

      my $var if $test;

      I see nothing that invalidates Eily's example of:

      my $var = 1 if $test;

      Another important point from that is: "Future versions of perl might do something different from the version of perl you try it out on."

      I don't think showing us the results of just two tests is particularly meaningful.

      [While it's probably a moot point, your second one-liner (with my $c = 1 if 0) doesn't indicate whether $c's value is a zero-length string or undef.]

      -- Ken

        Hi Ken,

        Thank you for your answer and I have usually the highest regard for your posts (and I upvoted your answer even though I still disagree with it, because I think it is well explained). To set the record straight, I am not trying to invalidate Eily's example, far from that, I am just trying to understand what exactly is undefined behavior here. And I am still not convinced at all that:

        my $var if $test;
        and
        my $var = 1 if $test;
        are equivalent in terms of the behavior being defined or not. These are two quite different types of statements. Assuming just one second, only for the sake of argument, they had both a defined behavior, I would still consider the first one as almost entirely useless (and deserving to be undefined), and the second one as making some sense (although lacking clarity, to say the least). Therefore, if the author of the documentation meant to say that my $var = 1 if $test; also has undefined behavior, then I would submit that this should probably be added to the documentation, because having someone using this second type of construct is much more likely than than the first one.

        Again, I am not saying that Eily is wrong, I just don't know and I truly would like to know. While I usually would probably not use something like:

        my $var = 1 if $test;
        I would really not swear that I have never used something like:
        my $value = $1 if $foo =~ /^\w+(\d+)/; do_something($value) if defined $value;
        And, as far as I can say, I would expect this to work fine.

        Concerning the one-liners, I agree that they were very short examples I added at the last minute to my post, this is an improved version of them:

        $ perl -Mstrict -Mwarnings -e ' my $c = 1 if 1; print $c;' 1 ~ $ perl -Mstrict -Mwarnings -e ' my $c if 1; print $c;' Use of uninitialized value $c in print at -e line 1.
        I am not saying that observed behavior is describing the Perl standard, but since there is no real Perl 5 standard, in a certain way, only the compiler can tell us what to think when the documentation is ambiguous. And I think the documentation is definitely ambiguous in that specific case. Having said that, I perfectly understand the warning: "Future versions of perl might do something different..." Just not sure that it applies to something like:
        my $var = 1 if $test;

Re^2: postfix syntax enlightenment
by hazylife (Monk) on Mar 30, 2014 at 15:59 UTC
    One thing is still not entirely clear to me: what if my is within the condition of a postfix if?
    use strict; if (my $x = 1) { print "x = $x\n" } # $x is not available outside of the if scope # this works, but is it valid? 1 if my $y = 3; print "y = $y\n"; for my $i (my @n = 1..3) { print "i = $i, n = (@n)\n" } # @n is not available here # the following code works as expected, but, again, is it valid? @ARGV = qw(/ /usr//local /etc/ sbin/); tr#/##s && s#(?<!^)/$## for my @copies = @ARGV; print "$_\n" for @copies;
      ... what if my is within the condition of a postfix if? ... is it valid?

      This is the way I look at it: The thing to remember is that the modifier clause (if that's the proper terminology) of a modified statement modifies the behavior of the statement. In order to do so, the modifier clause must always be evaluated. The ambiguity in a statement like
          my $x if $some_conditional;
      concerns whether (and when) the lexical definition is evaluated, but  $some_conditional (or whatever expression may be there) must always be evaluated.

      In a statement like
          0 if my $x = 1;
      there is no ambiguity: the lexical is always defined (and, in this example, initialized). Similarly, in the statement
          do_something($_) for my @ra = @rb;
      the for-loop initialization expression  my @ra = @rb must always be evaluated (including the definition and initialization of its lexical) in order that for may be able to control (i.e., modify the behavior of) the statement.

      So, is
          0 if my $x;
      and its ilk valid? Unquestionably (and unambiguously and without deprecation) yes, I would say. (But I'm too lazy right now to dig up a documentation citation.)

      Consider the following code. Also consider running | compiling it with  -MO=Deparse,-p added (often enlightening in these cases).

      c:\@Work\Perl\monks>perl -wMstrict -le "no warnings 'syntax'; ;; 0 if my $x = 42; print qq{$x}; ;; my @orig = qw(foo bar baz); tr{a-z}{A-Z} && printf qq{'$_' } for my @copy = @orig; print ''; print qq{(@orig) (@copy)}; ;; for (0 .. 2) { die 'Oops...' if my $x; print qq{\$x (still) undefined here} if not defined $x; $x = 42; print qq{\$x is $x here}; } " 42 'FOO' 'BAR' 'BAZ' (foo bar baz) (FOO BAR BAZ) $x (still) undefined here $x is 42 here $x (still) undefined here $x is 42 here $x (still) undefined here $x is 42 here

      (Also consider running your code with warnings enabled. And strict.)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1080134]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2014-08-31 11:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (294 votes), past polls