unary minus strangeness

Discussion in 'Perl Misc' started by sreservoir, Mar 28, 2010.

  1. sreservoir

    sreservoir Guest

    % perl -E'say -0'
    0
    % perl -E'say -undef'
    -0
    % perl -E'say(("-0")? 1 : 0)'
    1
    % perl -E'say((-undef)? 1 : 0)'
    0
    % perl -E'say ref -undef'


    what is a -0 supposed to be and why does undef evaluate to it? it is
    apparently not the string "-0", nor is it a ref with that string value;
    is this some sort of magical trickery?

    --

    "Six by nine. Forty two."
    "That's it. That's all there is."
    "I always thought something was fundamentally wrong with the universe."
     
    sreservoir, Mar 28, 2010
    #1
    1. Advertising

  2. sreservoir wrote:
    > % perl -E'say -0'
    > 0
    > % perl -E'say -undef'
    > -0
    > % perl -E'say(("-0")? 1 : 0)'
    > 1
    > % perl -E'say((-undef)? 1 : 0)'
    > 0
    > % perl -E'say ref -undef'
    >
    >
    > what is a -0 supposed to be and why does undef evaluate to it? it is
    > apparently not the string "-0", nor is it a ref with that string value;
    > is this some sort of magical trickery?


    perldoc perlop
    [ SNIP ]
    Symbolic Unary Operators
    Unary "!" performs logical negation, i.e., "not". See also "not"
    for a lower precedence version of this.

    Unary "-" performs arithmetic negation if the operand is numeric.
    ^^^^^^^^^^^^^^^^^^^^^^^^^
    [ *undef is not numeric.* ]

    If the operand is an identifier, a string consisting of a minus
    sign concatenated with the identifier is returned. Otherwise, if
    the string starts with a plus or minus, a string starting with
    the opposite sign is returned. One effect of these rules is that
    -bareword is equivalent to the string "-bareword". If, however,
    the string begins with a non-alphabetic character (excluding "+"
    or "-"), Perl will attempt to convert the string to a numeric and
    the arithmetic negation is performed. If the string cannot be
    cleanly converted to a numeric, Perl will give the warning
    Argument "the string" isn’t numeric in negation (-) at ....



    John
    --
    The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway
     
    John W. Krahn, Mar 28, 2010
    #2
    1. Advertising

  3. sreservoir

    sreservoir Guest

    On 3/28/2010 2:29 PM, John W. Krahn wrote:
    > sreservoir wrote:
    >> % perl -E'say -0'
    >> 0
    >> % perl -E'say -undef'
    >> -0
    >> % perl -E'say(("-0")? 1 : 0)'
    >> 1
    >> % perl -E'say((-undef)? 1 : 0)'
    >> 0
    >> % perl -E'say ref -undef'
    >>
    >>
    >> what is a -0 supposed to be and why does undef evaluate to it? it is
    >> apparently not the string "-0", nor is it a ref with that string value;
    >> is this some sort of magical trickery?

    >
    > perldoc perlop
    > [ SNIP ]
    > Symbolic Unary Operators
    > Unary "!" performs logical negation, i.e., "not". See also "not"
    > for a lower precedence version of this.
    >
    > Unary "-" performs arithmetic negation if the operand is numeric.
    > ^^^^^^^^^^^^^^^^^^^^^^^^^
    > [ *undef is not numeric.* ]
    >
    > If the operand is an identifier, a string consisting of a minus
    > sign concatenated with the identifier is returned. Otherwise, if
    > the string starts with a plus or minus, a string starting with
    > the opposite sign is returned. One effect of these rules is that
    > -bareword is equivalent to the string "-bareword". If, however,
    > the string begins with a non-alphabetic character (excluding "+"
    > or "-"), Perl will attempt to convert the string to a numeric and
    > the arithmetic negation is performed. If the string cannot be
    > cleanly converted to a numeric, Perl will give the warning
    > Argument "the string" isn’t numeric in negation (-) at ....


    you would think that would mean -'' would be '-'. but no, it's also
    -0. you're kind of making my point.

    --

    "Six by nine. Forty two."
    "That's it. That's all there is."
    "I always thought something was fundamentally wrong with the universe."
     
    sreservoir, Mar 28, 2010
    #3
  4. sreservoir

    Bo Lindbergh Guest

    For real strangeness, you need to mix negative zero, boolean context,
    and stringification.

    {
    my $strange=-0.0;
    print $strange ? "$strange is true\n" : "$strange is false\n";
    print $strange ? "$strange is true\n" : "$strange is false\n";
    }


    /Bo Lindbergh
     
    Bo Lindbergh, Mar 31, 2010
    #4
  5. On 2010-03-30, Bo Lindbergh <> wrote:
    > For real strangeness, you need to mix negative zero, boolean context,
    > and stringification.
    >
    > {
    > my $strange=-0.0;
    > print $strange ? "$strange is true\n" : "$strange is false\n";
    > print $strange ? "$strange is true\n" : "$strange is false\n";
    > }


    This is a bug. Read-only access should not change the value.

    Yours,
    Ilya
     
    Ilya Zakharevich, Mar 31, 2010
    #5
  6. sreservoir

    Marc Girod Guest

    On Mar 28, 10:56 pm, Ben Morrow <> wrote:

    > For some reason, undef gets numified as a floating-point
    > zero rather than an integral zero, so it can be negated.


    May I check that I understand this with respect to the excerpt of
    perlop John gave:

    $ perl -E'say undef'

    $ perl -E'say q()'

    $ perl -E'say -undef'
    -0
    $ perl -E'say -q()'
    0
    $ perl -E'say "-undef"'
    -undef

    > If the operand is an identifier, a string consisting of a minus
    > sign concatenated with the identifier is returned.


    So, not this case:
    undef is not an 'identifier', and the return is no '-undef'.

    > Otherwise, if the string starts with a plus or minus,
    > a string starting with the opposite sign is returned.


    No.

    > One effect of these rules is that -bareword is equivalent
    > to the string "-bareword".


    No.

    > If, however, the string begins with a non-alphabetic character
    > (excluding "+" or "-"), Perl will attempt to convert the
    > string to a numeric and the arithmetic negation is performed.


    I understand that this is what applies: undef is a 'non-alphabetic
    character'?
    There, undef is converted to 'floating-point 0', whereas q() (the
    empty string) is converted to 'integer 0'.

    > If the string cannot be cleanly converted to a numeric,
    > Perl will give the warning


    No: no warning.

    Thanks,
    Marc
     
    Marc Girod, Mar 31, 2010
    #6
  7. sreservoir

    Bo Lindbergh Guest

    In article <>,
    Ilya Zakharevich <> wrote:
    > On 2010-03-30, Bo Lindbergh <> wrote:
    > > For real strangeness, you need to mix negative zero, boolean context,
    > > and stringification.
    > >
    > > {
    > > my $strange=-0.0;
    > > print $strange ? "$strange is true\n" : "$strange is false\n";
    > > print $strange ? "$strange is true\n" : "$strange is false\n";
    > > }

    >
    > This is a bug. Read-only access should not change the value.


    Would you call this example the same bug, a different bug, or not a bug?
    {
    my $strange="-0";
    print "- $strange == ", -$strange, "\n";
    my $ignored=0+$strange;
    print "- $strange == ", -$strange, "\n";
    }

    Ditto for this one.
    {
    my($one,$two)=("12","21");
    print "$one | $two == ", $one | $two, "\n";
    my $ignored=$one+$two;
    print "$one | $two == ", $one | $two, "\n";
    }


    /Bo Lindbergh
     
    Bo Lindbergh, Mar 31, 2010
    #7
  8. On 2010-03-31, Bo Lindbergh <> wrote:
    >> > {
    >> > my $strange=-0.0;
    >> > print $strange ? "$strange is true\n" : "$strange is false\n";
    >> > print $strange ? "$strange is true\n" : "$strange is false\n";
    >> > }

    >>
    >> This is a bug. Read-only access should not change the value.


    .... Reading string value of -0.0 changes TRUE/FALSE...

    > Would you call this example the same bug, a different bug, or not a bug?
    > {
    > my $strange="-0";
    > print "- $strange == ", -$strange, "\n";
    > my $ignored=0+$strange;
    > print "- $strange == ", -$strange, "\n";
    > }


    .... Reading NUM value of "-0" changes the effect of unary minus.

    It looks like different bugs - but they may have the same fix.... ;-)

    > Ditto for this one.
    > {
    > my($one,$two)=("12","21");
    > print "$one | $two == ", $one | $two, "\n";
    > my $ignored=$one+$two;
    > print "$one | $two == ", $one | $two, "\n";
    > }


    Not a bug - just a documented brokenness of |-operator...

    Hope this helps,
    Ilya
     
    Ilya Zakharevich, Apr 1, 2010
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andrew Ward
    Replies:
    6
    Views:
    714
    Ron Natalie
    Sep 26, 2003
  2. Marc

    Semantics of unary minus

    Marc, Feb 12, 2006, in forum: C Programming
    Replies:
    13
    Views:
    507
  3. Matthew  Cook
    Replies:
    6
    Views:
    516
  4. Sam Stephenson
    Replies:
    9
    Views:
    251
    Caleb Clausen
    Nov 7, 2005
  5. Todd Burch
    Replies:
    3
    Views:
    168
    Jonas Roberto de Goes Filho (sysdebug)
    Aug 27, 2007
Loading...

Share This Page